/** Tick handler. Called every second. Also called on the minute for "heartbeat" working reminders. */ void pomOnTick(struct tm *tick_time, TimeUnits units_changed) { if (app.timer.state == PomStateReady) return; app.ticksRemaining--; // check for time up // Note: because this returns, you have an extra second to see the change over. feature, not a bug. if (app.ticksRemaining < 0) { if (app.timer.state == PomStateWorking) { // you finished the pomodoro! congrats! app.timer.completedPoms++; if (app.timer.lastPomHour < 6 && tick_time->tm_hour >= 6) { app.timer.completedPoms = 0; } app.timer.lastPomHour = tick_time->tm_hour; vibes_short_pulse(); light_enable_interaction(); pomSetState(PomStateResting); return; } else if (app.timer.state == PomStateResting) { // time to start another pomodoro. vibes_enqueue_custom_pattern(VIBRATE_DIT_DIT_DAH); light_enable_interaction(); pomSetState(app.settings.autoContinue? PomStateWorking : PomStateReady); return; } } bool isWorking = (app.timer.state == PomStateWorking); // bool isResting = (app.timer.state == PomStateResting); // heartbeat if (isWorking && app.settings.vibrateWhileWorking && (app.ticksRemaining % app.settings.vibrateTicks) == 0) { vibes_enqueue_custom_pattern(VIBRATE_MINIMAL); } // TODO resize inverter /* float pctRemaining = (app.ticksRemaining + 0.0) / app.totalTicks; GRect inverterFrame = GRect(0, 0, windowSize.w, 0); if (isWorking) { inverterFrame.size.h = (1.0 - pctRemaining) * windowSize.h; } else if (isResting) { inverterFrame.size.h = pctRemaining * windowSize.h; } layer_set_frame(inverter_layer_get_layer(app.inverterLayer), inverterFrame); */ // set timer text formatTime(gTimeString, app.ticksRemaining); text_layer_set_text(app.timeTextLayer, gTimeString); // redraw! layer_mark_dirty(window_get_root_layer(app.mainWindow)); }
static void menu_draw_row_callback(GContext* ctx, const Layer *cell_layer, MenuIndex *cell_index, void *data) { int index = cell_index->row; if (nrbyStps_scrollIndex == index) { if (nrbyStps_scrollOffset == 0) { strcpy(nrbyStps_scrollTmp, busStops[index].stopDescription); } int txtWidth = textWidth(nrbyStps_scrollTmp); if (txtWidth > MAX_VISIBLE) { int charIndex = 0; int maxLen = strlen(busStops[index].stopDescription); for (int i=nrbyStps_scrollOffset; i<maxLen; i++) { nrbyStps_scrollTmp[charIndex++] = busStops[index].stopDescription[i]; } nrbyStps_scrollTmp[charIndex] = '\0'; nrbyStps_scrollingStillRequired = true; if (nrbyStps_scrollIndex == index) { light_enable_interaction(); } } menu_cell_basic_draw(ctx, cell_layer, nrbyStps_scrollTmp, busStops[index].stopDetails, NULL); } else { menu_cell_basic_draw(ctx, cell_layer, busStops[index].stopDescription, busStops[index].stopDetails, NULL); } }
static void menu_selection_changed(struct MenuLayer *menu_layer, MenuIndex new_index, MenuIndex old_index, void *callback_context) { switch (new_index.section) { case 0: selectedMenuCell = new_index.row; light_enable_interaction(); break; } }
static void show_main_menu(char* categories) { _numCategories = split_string(categories, _categoryArray); APP_LOG(APP_LOG_LEVEL_DEBUG, "Loaded main menu"); show_category_view(_categoryArray, _numCategories); light_enable_interaction(); }
void ExtendBackLight(){ //Turn the lights on! light_enable_interaction(); //Reset the time for another second BackLightTimer = app_timer_register(1000, ExtendBackLight, NULL); }
static void handle_bluetooth_connected () { window_stack_remove(bluetooth_disconnected_splash_window, true); window_stack_push(bluetooth_connected_splash_window, true); vibes_long_pulse(); // Hide splash screen app_timer_register(2000, (void*)hide_bluetooth_connected_splash_window, NULL); light_enable_interaction(); //s_bluetooth_disconnection_dismissal_attempt = 0; }
void check_notification(int distance) { if(distance < 0){ return; } else if (notified == 0 && distance < NOTIFY_DISTANCE) { notified = 1; vibes_double_pulse(); light_enable_interaction(); } else if (notified == 1 && distance > RESET_DISTANCE) { reset_notification(); } }
// Callbck for when the device status has been fetched void device_status_fetched(int device_id, DeviceStatus status, char *status_changed) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Status fetched - ID: %d, Status: %d, Selected ID: %d", device_id, status, g_device_id_list[g_device_selected]); reset_inactivity_timer(); if (g_device_id_list[g_device_selected] == device_id) { if (s_device_status_target != DSNone) { // If expecting the device status to change (e.g. Garage door opening/closing) cancel_status_check(); if (((status == DSVGDOOpen) ? DSOnOpen : status) != s_device_status_target) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Status still not reached target, checking again in 2 seconds..."); // Still not reached target status, so check again after 2 seconds status_change_check_timer = app_timer_register(2000, status_change_check, NULL); } else { APP_LOG(APP_LOG_LEVEL_DEBUG, "Status has reached target"); // Status changed, so stop checking cancel_timeout(); s_device_status_target = DSNone; s_device_status = status; strncpy(s_status_changed, status_changed, sizeof(s_status_changed)); s_status_changed[sizeof(s_status_changed)-1] = '\0'; show_device_status(status, status_changed); light_enable_interaction(); vibes_short_pulse(); } } else { // Not expecting status to change, so just update the display cancel_status_check(); if (status != s_device_status) { s_device_status = status; light_enable_interaction(); } strncpy(s_status_changed, status_changed, sizeof(s_status_changed)); s_status_changed[sizeof(s_status_changed)-1] = '\0'; show_device_status(status, status_changed); } } }
static void menu_select_callback(MenuLayer *menu_layer, MenuIndex *cell_index, void *data) { switch (cell_index->section) { case 0: if (numMenuItems > 0) { do_post(_latestUrl[cell_index->row]); APP_LOG(APP_LOG_LEVEL_DEBUG, _latestUrl[cell_index->row]); APP_LOG(APP_LOG_LEVEL_DEBUG, _latest[cell_index->row]); light_enable_interaction(); show_animation(); } break; } }
// Accelerometer Handler Update // s_nearbyStopsWindow: get current bus stop selection and scrolling offset. Request new data. // s_busArrivalsWindow: get current bus service selection and scrolling offset. Reqeust new data. static void accelerometerHandler(AccelAxisType axis, int32_t direction) { light_enable_interaction(); time_t now = time(NULL); if (difftime(now, lastUpdate) < MINIMUM_UPDATE_SECONDS) { return; } if (window_stack_get_top_window() == s_nearbyStopsWindow) { requestData("location"); } else if (window_stack_get_top_window() == s_busArrivalsWindow) { requestData(lastStopRequest); } }
static void handle_bluetooth_disconnected () { window_stack_remove(bluetooth_connected_splash_window, true); window_stack_push(bluetooth_disconnected_splash_window, true); uint32_t vibes_pluse_segments[] = { 200, 100, 200, 100, 200, 100, 200, 100, 200 }; VibePattern vibes_pluse_pattern = { .durations = vibes_pluse_segments, .num_segments = ARRAY_LENGTH(vibes_pluse_segments), }; vibes_enqueue_custom_pattern(vibes_pluse_pattern); light_enable_interaction(); // Hide splash screen app_timer_register(5000, (void*)hide_bluetooth_disconnected_splash_window, NULL); }
void InboxRefresh() { if (s_visible) { menu_layer_reload_data(&s_menu_layer); K9_APP_LOG(APP_LOG_LEVEL_DEBUG, "reloaded menu data"); } if (s_waitingForData) { s_waitingForData = false; PleaseWaitHide(); InboxShow(0); light_enable_interaction(); } }
/* * Common stuff we always do at the end of setup */ EXTFN void morpheuz_load_standard_postamble() { read_internal_data(); read_config_data(); // Start clock tick_timer_service_subscribe(MINUTE_UNIT, handle_minute_tick); battery_state_handler(battery_state_service_peek()); battery_state_service_subscribe(&battery_state_handler); bluetooth_state_handler(bluetooth_connection_service_peek()); bluetooth_connection_service_subscribe(bluetooth_state_handler); init_morpheuz(); light_enable_interaction(); }
static void update_time() { // Get a tm structure time_t temp = time(NULL); struct tm *tick_time = localtime(&temp); if (tick_time->tm_min == 00) { vibes_short_pulse(); light_enable_interaction(); } if (tick_time->tm_min == 00 || tick_time->tm_min == 30) { request_weather(); } // Create a long-lived buffer static char hour_buffer[] = "00"; static char min_buffer[] = "00"; static char am_buffer[] = "00"; strftime(date_buffer, sizeof(date_buffer), " %a \n %b \n %e", tick_time); // Write the current hours and minutes into the buffer if(clock_is_24h_style() == true) { // Use 24 hour format strftime(hour_buffer, sizeof("00"), "%l", tick_time); strftime(min_buffer, sizeof("00"), "%M", tick_time); //"%H:%M", tick_time); strftime(am_buffer, sizeof("00"), "%p", tick_time); } else { // Use 12 hour format strftime(hour_buffer, sizeof("00"), "%l", tick_time); strftime(min_buffer, sizeof("00"), "%M", tick_time); strftime(am_buffer, sizeof("00"), "%p", tick_time); } // Display this time on the TextLayer //text_layer_set_text(s_time_layer, buffer); text_layer_set_text(hour_layer, hour_buffer); text_layer_set_text(min_layer, min_buffer); text_layer_set_text(date_layer, date_buffer); text_layer_set_text(am_layer, am_buffer); handle_battery(battery_state_service_peek()); }
void inbox_received_callback(DictionaryIterator *iterator, void *context) { // Store incoming information static char temperature_buffer[3]; static char weather_layer_buffer[3]; static char title_buffer[100]; static char warning_buffer[100]; static char warningb_buffer[100]; static char suburb_buffer[100]; Tuple *t = dict_read_first(iterator); while(t != NULL) { if(t->key == KEY_TEMPERATURE) { snprintf(temperature_buffer, sizeof(temperature_buffer), "%d", (int)t->value->int32); snprintf(weather_layer_buffer, sizeof(weather_layer_buffer), temperature_buffer); text_layer_set_text(s_weather_layer, weather_layer_buffer); } else if (t->key == KEY_CONDITIONS) { conditionId = (int *)t->value->int32; layer_set_update_proc(s_weather_icon_layer, set_weather_icon); } else if(currentlyPrepTime || currentlyTravelTime) { if (t->key == KEY_TRAFFIC_TITLE ) { snprintf(title_buffer, sizeof(title_buffer), "%s", t->value->cstring); text_layer_set_text(s_travel_row_one_layer, title_buffer); light_enable_interaction(); } else if (t->key == KEY_TRAFFIC_WARNING_ONE && (currentlyPrepTime || currentlyTravelTime)) { snprintf(warning_buffer, sizeof(warning_buffer), "%s", t->value->cstring); text_layer_set_text(s_travel_row_two_layer, warning_buffer); } else if (t->key == KEY_TRAFFIC_WARNING_TWO && (currentlyPrepTime || currentlyTravelTime)) { snprintf(warningb_buffer, sizeof(warningb_buffer), "%s", t->value->cstring); text_layer_set_text(s_travel_row_three_layer, warningb_buffer); } else if (t->key == KEY_TRAFFIC_DIRECTION && (currentlyPrepTime || currentlyTravelTime)) { snprintf(suburb_buffer, sizeof(suburb_buffer), "%s", t->value->cstring); text_layer_set_text(s_travel_row_four_layer, suburb_buffer); } } t = dict_read_next(iterator); } }
void show_time(struct tm* t) { if(pi_status & SHOWN) { bitmap_layer_set_bitmap(background, background_bmp); gbitmap_destroy(pi); } pi_status = DISABLED; if(t->tm_hour == 3 && t->tm_min == 14) { light_enable_interaction(); pi_status |= ENABLED; } unsigned short hour = (clock_is_24h_style() ? t->tm_hour : (t->tm_hour > 12 ? t->tm_hour - 12 : t->tm_hour)); load_number(0, 0, hour / 10); load_number(0, 1, hour % 10); load_number(1, 0, t->tm_min / 10); load_number(1, 1, t->tm_min % 10); }
void handle_init(AppContextRef ctx) { // makes sure the light is enabled at the beginning of the app light_enable_interaction(); window_init(&window, "Torch"); window_stack_push(&window, true /* Animated */); window_set_background_color(&window, GColorWhite); // window_set_fullscreen(&window, true); // removes the clock displayed on the top of the screen. text_layer_init(&textLayer, window.layer.frame); text_layer_set_text(&textLayer, "Backlight is ON as long as this screen is displayed."); text_layer_set_font(&textLayer, fonts_get_system_font(FONT_KEY_GOTHIC_24)); text_layer_set_text_alignment(&textLayer, GTextAlignmentCenter); layer_add_child(&window.layer, &textLayer.layer); // TODO : set text in thé midole of thé screen app_timer_send_event(ctx, REFRESH_LIGHT_TIMEOUT /* milliseconds */, 0 /* Not using a cookie value */); }
static void accel_handler(AccelData *data, uint32_t num_samples) { // If facing up Light It Up!!! if(((data[0].z < -980) && (data[0].z >-1020))&& ((data[1].z < -980) && (data[1].z >-1020)) && ((data[2].z < -980) && (data[2].z >-1020)) ){ // light_enable_interaction(); update_time(); //vibes_double_pulse(); } int tol = 10; int ztop = data[0].z + tol; int zbot = data[0].z - tol; int xtop = data[0].x + tol; int xbot = data[0].x - tol; int ytop = data[0].y + tol; int ybot = data[0].y - tol; if((data[1].z < ztop)&&(data[1].z > zbot) && (data[2].z < ztop)&&(data[2].z > zbot)&& (data[1].y < ytop)&&(data[1].y > ybot) && (data[2].y < ytop)&&(data[2].y > ybot)&& (data[1].x < xtop)&&(data[1].x > xbot) && (data[2].x < xtop)&&(data[2].x > xbot)){ vibes_enqueue_custom_pattern(pat); light_enable_interaction(); } }
/* * Alarm timer loop */ static void recure_alarm() { if (vib_count >= ALARM_MAX_ITERATIONS) { alarm_in_motion = NO; // Reschedule if no stop alarm and snooze is active if (config.snooze > 0) { // This should not be changed in the meanwhile snooze_active = YES; snooze_timer = app_timer_register(config.snooze * 1000 * 60, snooze_tick, NULL); } return; } // Vibrate vibes_long_pulse(); alarm_timer = app_timer_register(ALARM_TIME_BETWEEN_ITERATIONS, recure_alarm, NULL); vib_count++; if (vib_count % 3 == 0) { light_enable_interaction(); } }
void select_click_callback( struct MenuLayer *menu_layer, MenuIndex *cell_index, void *callback_context) { // Get the value for this index char str_buffer[BUFFER_SIZE]; read_data_value(keys[cell_index->row], str_buffer); text_window = window_create(); // This memory leaks text_layer = text_layer_create(GRect(0, 0, 144, 154)); char value_buffer[BUFFER_SIZE]; read_data_value(keys[cell_index->row], value_buffer); snprintf(buf, 300, "%s", value_buffer); text_layer_set_text(text_layer, buf); text_layer_set_font(text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD)); text_layer_set_text_alignment(text_layer, GTextAlignmentCenter); // Add the text layer to the window layer_add_child(window_get_root_layer(text_window), text_layer_get_layer(text_layer)); window_stack_push(text_window, true); light_enable_interaction(); }
void timer_call() /* эта функция вызывается при срабатываниии таймера и при первом запуске перебора */ { if (first_time == false)/* если запускается не в первый раз... */ { bitmap_layer_destroy(image_layer); /* ...то удаляем старый слой, чтобы он не мешался позади... */ gbitmap_destroy(image); /* ...и очищаем память от предыдущей картинки */ } first_time = false; /* сбрасываем флаг первого запуска */ image_layer = bitmap_layer_create(GRect(rand()%(144-75), rand()%(168-75), 75, 75)); /* создаем слой со случайными координатами, но в пределах экрана */ layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(image_layer)); /* делаем его дочерним */ image = gbitmap_create_with_resource(images[rand() % 6]); /* загружаем в память случайную картинку из подключенных ресурсов */ bitmap_layer_set_bitmap(image_layer, image); /* выводим загруженную картинку в слой */ light_enable_interaction(); /* включаем подсветку */ if (timer_delay < 300*1000 ) /* если задержка еще не достигла 300мс... */ { timer_delay=timer_delay/0.7; /* ...увеличиваем задержку... */ app_timer_register(timer_delay/1000, timer_call, NULL); /* ...и взводим таймер заново */ } else /* если задержка уже больше 300мс... */ { timer_delay=1; /* сбрасываем таймер на начало и выходим - сообщение и картинку мы же уже показали */ } }
void success(int32_t cookie, int http_status, DictionaryIterator *dict, void *ctx) { if (cookie != PBLINDEX_NAMES_COOKIE && cookie != PBLINDEX_VALUES_COOKIE) return; int li = cookie == PBLINDEX_NAMES_COOKIE ? 0 : 1; for (int i=0; i<NUM_LINES; i++) { Tuple *value = dict_find(dict, i); if (value) { static char str[2][NUM_LINES][16]; strcpy(str[li][i], value->value->cstring); text_layer_set_text(&textLayer[li][i], str[li][i]); } else { text_layer_set_text(&textLayer[li][i], "-"); } } if (!li) { request_values(); } else { light_enable_interaction(); //#if MAKE_SCREENSHOT // http_capture_send(20); //#endif } }
static void prv_window_load(Window *window) { GoalStarGoalEventWindowData *data = window_get_user_data(window); if (!data) { return; } Layer *window_root_layer = window_get_root_layer(window); const GRect window_root_layer_bounds = layer_get_bounds(window_root_layer); data->goal_reached_sequence = gdraw_command_sequence_create_with_resource(RESOURCE_ID_GOAL_REACHED); data->goal_reached_sequence_layer = layer_create(window_root_layer_bounds); Layer *goal_reached_sequence_layer = data->goal_reached_sequence_layer; layer_set_update_proc(goal_reached_sequence_layer, prv_goal_reached_sequence_layer_update_proc); layer_add_child(window_root_layer, goal_reached_sequence_layer); data->goal_reached_sequence_timer = app_timer_register(ANIMATION_FRAME_INTERVAL_MS, prv_goal_reached_sequence_timer_handler, data); prv_vibrate(); light_enable_interaction(); }
void handle_timer(AppContextRef ctx, AppTimerHandle handle, uint32_t cookie) { light_enable_interaction(); app_timer_send_event(ctx, REFRESH_LIGHT_TIMEOUT /* milliseconds */, cookie /* Not using a cookie value */); }
void reset_notification() { notified = 0; vibes_long_pulse(); light_enable_interaction(); }
static void cb_in_received_handler(DictionaryIterator *iter, void *context) { APP_LOG(APP_LOG_LEVEL_DEBUG, "Incoming data"); // Reset ErrorExists = 0; text_layer_set_text(error_text_layer, ""); // Set any messages Tuple *message_tuple = dict_find(iter, KEY_MESSAGE); if(message_tuple){ strcpy(msg_str, message_tuple->value->cstring); text_layer_set_text(message_text_layer, msg_str); layer_mark_dirty(text_layer_get_layer(message_text_layer)); } // Get the bitmap Tuple *size_tuple = dict_find(iter, KEY_SIZE); if(size_tuple){ if(data_image) free(data_image); data_size = size_tuple->value->uint32; data_image = malloc(data_size); } // Set the image Tuple *image_tuple = dict_find(iter, KEY_IMAGE); Tuple *index_tuple = dict_find(iter, KEY_INDEX); if (index_tuple && image_tuple) { int32_t index = index_tuple->value->int32; //APP_LOG(APP_LOG_LEVEL_DEBUG, "image received index=%ld size=%d", index, image_tuple->length); memcpy(data_image + index,&image_tuple->value->uint8,image_tuple->length); if(image_tuple->length < CHUNK_SIZE){ // Clear the image if(image){ gbitmap_destroy(image); image = NULL; } #ifdef PBL_COLOR image = gbitmap_create_from_png_data(data_image, data_size); #else image = gbitmap_create_with_data(data_image); #endif bitmap_layer_set_bitmap(image_layer, image); layer_mark_dirty(bitmap_layer_get_layer(image_layer)); text_layer_set_text(message_text_layer,""); layer_mark_dirty(text_layer_get_layer(message_text_layer)); vibes_short_pulse(); light_enable_interaction(); ImgLoaded = 1; Loading = 0; text_layer_set_text(username_text_layer, usr_str); text_layer_set_background_color(username_text_layer, GColorWhite); if(ErrorExists == 1){ text_layer_set_background_color(username_text_layer, GColorClear); } layer_mark_dirty(text_layer_get_layer(username_text_layer)); } } // Set any errors Tuple *error_tuple = dict_find(iter, KEY_ERROR); if(error_tuple){ text_layer_set_text(message_text_layer,""); layer_mark_dirty(text_layer_get_layer(message_text_layer)); // Clear the image if(image){ gbitmap_destroy(image); if(data_image){ free(data_image); } image = NULL; bitmap_layer_set_bitmap(image_layer, image); } Loading = 0; ErrorExists = 1; #ifdef PBL_COLOR image = gbitmap_create_with_resource(RESOURCE_ID_ERROR_B); text_layer_set_text_color(error_text_layer, GColorBlack); #else image = gbitmap_create_with_resource(RESOURCE_ID_ERROR_A); #endif bitmap_layer_set_bitmap(image_layer, image); layer_mark_dirty(bitmap_layer_get_layer(image_layer)); text_layer_set_text(error_text_layer, error_tuple->value->cstring); layer_mark_dirty(text_layer_get_layer(error_text_layer)); vibes_short_pulse(); light_enable_interaction(); } // Prepare the username Tuple *username_tuple = dict_find(iter, KEY_USERNAME); if(username_tuple){ strcpy(usr_str, username_tuple->value->cstring); prepend(usr_str, " "); //text_layer_set_text(username_text_layer, usr_str); } // Set the likes Tuple *likes_tuple = dict_find(iter, KEY_LIKES); if(likes_tuple){ strcpy(likes_str, likes_tuple->value->cstring); update_likes(likes_str); } // Set the comments Tuple *comments_tuple = dict_find(iter, KEY_COMMENTS); if(comments_tuple){ strcpy(comments_str, comments_tuple->value->cstring); update_comments(comments_str); } // Set the caption Tuple *caption_tuple = dict_find(iter, KEY_CAPTION); if(caption_tuple){ strcpy(capt_str, caption_tuple->value->cstring); update_caption(capt_str); } }
/* * Timer handling. Includes a hold off for a period of time if there is resource contention */ void handle_calendar_timer(void *cookie) { // Show the alert and let the world know if ((int)cookie >= ALERT_EVENT && (int)cookie <= ALERT_EVENT + MAX_EVENTS) { int num = (int)cookie - ALERT_EVENT; if (timer_rec[num].active == false) return; // Already had the data for this event deleted - cannot show it. timer_rec[num].active = false; for (int i = num + 1; i < max_entries; i++) { if (timer_rec[i].active == true) { handle_calendar_timer((void *)100 + i); vibes_short_pulse(); light_enable_interaction(); return; } } //draw_date(); return; } if ((int)cookie >= 100 && (int)cookie <= 100 + MAX_EVENTS) { int num = (int)cookie - 100; if (timer_rec[num].active == false) return; // Already had the data for this event Event event = events[num]; // Compute the event start time as a figure in ms int time_position = 9; if (event.start_date[5] != '/') time_position = 6; int hour = a_to_i(&event.start_date[time_position],2); int minute_position = time_position + 3; if (event.start_date[time_position + 1] == ':') minute_position = time_position + 2; int minute = a_to_i(&event.start_date[minute_position],2); uint32_t event_in_ms = (hour * 3600 + minute * 60) * 1000; // Get now as ms time_t rawtime; time(&rawtime); struct tm *time = localtime(&rawtime); uint32_t now_in_ms = (time->tm_hour * 3600 + time->tm_min * 60 + time->tm_sec) * 1000; // Work out the alert interval int32_t alert_event = event_in_ms - now_in_ms; // If this is negative then we are after the alert period if (alert_event >= 0) { set_relative_desc(num, alert_event); display_event_text(timer_rec[num].event_desc, timer_rec[num].relative_desc); if (alert_event == 0) { timer_rec[num].handle = app_timer_register(30000, handle_calendar_timer, (void *)ALERT_EVENT + num); vibes_double_pulse(); light_enable_interaction(); } else if (alert_event > 0) { timer_rec[num].handle = app_timer_register(60000 - time->tm_sec * 1000, handle_calendar_timer, (void *)100 + num); } } return; } // Server requests if ((int)cookie != REQUEST_CALENDAR_KEY) return; // If we're going to make a call to the phone, then a dictionary is a good idea. DictionaryIterator *iter; app_message_outbox_begin(&iter); // We didn't get a dictionary - so go away and wait until resources are available if (!iter) { // Can't get an dictionary then come back in a second app_timer_register(1000, handle_calendar_timer, (void *)cookie); return; } // Make the appropriate call to the server if ((int)cookie == REQUEST_CALENDAR_KEY) { calendar_request(iter); app_timer_register(REQUEST_CALENDAR_INTERVAL_MS, handle_calendar_timer, (void *)cookie); } }
/* * Timer handling. Includes a hold off for a period of time if there is resource contention */ void handle_calendar_timer(AppContextRef app_ctx, AppTimerHandle handle, uint32_t cookie) { // If we're rotating the visible event, get on with it. Slower overnight to save power if (cookie == ROTATE_EVENT) { // Clobber the timer app_timer_cancel_event(app_ctx, handle); // Show next event show_next_event(); // Kick off new timer if (is_overnight()) app_timer_send_event(app_ctx, ROTATE_EVENT_INTERVAL_OVERNIGHT_MS, cookie); else app_timer_send_event(app_ctx, ROTATE_EVENT_INTERVAL_MS, cookie); // Retire from active duty return; } // Show the alert and let the world know if (cookie >= ALERT_EVENT && cookie <= (ALERT_EVENT + (MAX_EVENTS * 2))) { app_timer_cancel_event(app_ctx, handle); int num = cookie - ALERT_EVENT; if (g_timer_rec[num].active == false) return; // Already had the data for this event deleted - cannot show it. g_timer_rec[num].active = false; g_showing_alert = true; set_event_display(g_timer_rec[num].event_desc, g_timer_rec[num].relative_desc, g_timer_rec[num].location, 0); set_invert_when_showing_event(true); app_timer_send_event(app_ctx, 30000, RESTORE_DATE); app_timer_send_event(app_ctx, 15000, SECOND_ALERT); vibes_double_pulse(); light_enable_interaction(); return; } // Let us know again if (cookie == SECOND_ALERT) { app_timer_cancel_event(app_ctx, handle); vibes_double_pulse(); light_enable_interaction(); return; } // Put the date back into the display area if (cookie == RESTORE_DATE) { app_timer_cancel_event(app_ctx, handle); g_showing_alert = false; show_next_event(); set_invert_when_showing_event(false); return; } // Fire the calendar request if (cookie == REQUEST_CALENDAR_KEY) { app_timer_cancel_event(app_ctx, handle); calendar_request(); } }
static void layer_update_callback(Layer *me, GContext* ctx) { // preparations GRect bounds = layer_get_bounds(me); uint16_t width = bounds.size.w; uint16_t height = bounds.size.h; uint16_t stride = (bounds.size.w + 31) / 32 * 32; uint16_t max = (height - 1) * stride + width; uint16_t shake = stride - width; uint16_t shake_stride = shake * stride; // handle shake if (do_shake) { do_shake = false; light_enable_interaction(); for (uint16_t i = 0, j = rand(); i < NUM_FLAKES; i++, j+=31) { for (uint16_t k = 0; k < 2; k++, j+=31) { uint16_t next = flakes[i] + j % (max * 2) - max; if (next < max && next % stride < width && get_pixel(ctx, next) == GColorBlack) { flakes[i] = next; break; } } } last_time = 0; } // update time text time_t t = time(NULL); if (t / UPDATE_S > last_time) { last_time = t / UPDATE_S; char time_text[6]; clock_copy_time_string(time_text, sizeof(time_text)); graphics_context_set_fill_color(ctx, GColorBlack); graphics_fill_rect(ctx, bounds, 0, GCornerNone); GRect rect = (GRect) {{0, 60}, {width, 50}}; GFont font = fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD); graphics_draw_text(ctx, time_text, font, rect, GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, NULL); graphics_context_set_stroke_color(ctx, GColorWhite); for (uint16_t i = 0, j = rand(); i < NUM_FLAKES; i++) { if (get_pixel(ctx, flakes[i]) == GColorBlack) { graphics_draw_pixel(ctx, GPoint(flakes[i] % stride, flakes[i] / stride)); } else { for (uint16_t k = 0; k < 8; k++, j++) { uint16_t next = flakes[i] + (j % 9 / 3 - 1) * shake_stride + (j % 3 - 1) * shake; if (next < max && next % stride < width && get_pixel(ctx, next) == GColorBlack) { flakes[i] = next; graphics_draw_pixel(ctx, GPoint(flakes[i] % stride, flakes[i] / stride)); break; } } } } } // apply physics AccelData accel = {.x = 0, .y = 0, .z = 0}; accel_service_peek(&accel); uint16_t absx = accel.x < 0 ? -accel.x : accel.x; uint16_t absy = accel.y < 0 ? -accel.y : accel.y; uint16_t span = (absx + absy + 10) * SPEED; for (uint16_t i = 0, j = rand(), k = rand(), l = rand(); i < span; i++, j++, k++, l++) { uint16_t index = j % NUM_FLAKES; uint16_t next = flakes[index]; int16_t sideway = k % 3 == 0 ? l % 5 - 2 : 0; int16_t accx = accel.x + accel.y * sideway; int16_t accy = accel.y - accel.x * sideway; absx = accx < 0 ? -accx : accx; absy = accy < 0 ? -accy : accy; if (absx > absy || k % absy < absx) { if (accx > 0) { next++; } else { next--; } } if (absy > absx || l % absx < absy) { if (accy > 0) { next -= stride; } else { next += stride; } } if (next < max && next % stride < width && get_pixel(ctx, next) == GColorBlack) { graphics_context_set_stroke_color(ctx, GColorBlack); graphics_draw_pixel(ctx, GPoint(flakes[index] % stride, flakes[index] / stride)); graphics_context_set_stroke_color(ctx, GColorWhite); graphics_draw_pixel(ctx, GPoint(next % stride, next / stride)); flakes[index] = next; } } if (!timer) timer = app_timer_register(UPDATE_MS, timer_callback, NULL); } static void handle_accel(AccelData *accel_data, uint32_t num_samples) { // or else I will crash } static void accel_tap_handler(AccelAxisType axis, int32_t direction) { do_shake = true; } static void root_update_callback(Layer *me, GContext* ctx) { // hack to prevent screen cleaning } static void window_load(Window *window) { Layer *window_layer = window_get_root_layer(window); layer_set_update_proc(window_layer, root_update_callback); GRect bounds = layer_get_bounds(window_layer); layer = layer_create(bounds); layer_set_update_proc(layer, layer_update_callback); layer_add_child(window_layer, layer); uint16_t width = bounds.size.w; uint16_t height = bounds.size.h; uint16_t stride = (bounds.size.w + 31) / 32 * 32; for (uint16_t i = 0; i < NUM_FLAKES; i++) { flakes[i] = rand() % height * stride + rand() % width; } }