void *ai_audio_context_save( uint8_t *status, uint16_t *size ) { if( !ai_async_audio_context_save() ) { *status = false; return NULL; } do { AI_SYNC_TASK_CALL_BACK(); ai_async_cmd_task(); }while( !is_ai_async_cmd_finished() ); *status = ai_async_cmd_out_status(); *size = ai_async_cmd_out_SizeArrayU8(); return (void *)ai_async_cmd_out_PtrArrayU8(); }
static void track_changed_task(struct state_machine_context *state_m) { // By default, the command executed is asynchronous. state_m->async_cmd = true; Ai_player_flag_t player_flag_temp; switch (state_m->state) { case STATE_TRACK_CHANGED_ENTRY_POINT: memset(&state_m->info, 0, sizeof(struct file_info)); ai_async_audio_nav_file_info_duration(); state_m->state = STATE_TRACK_CHANGED_TOTAL_TIME; break; // Record total time info and call file name. case STATE_TRACK_CHANGED_TOTAL_TIME: state_m->info.total_time = ai_async_cmd_out_u32(); ai_async_audio_nav_getname(); state_m->state = STATE_TRACK_CHANGED_FILE_NAME; break; // Record file name information and call for artist metadata. case STATE_TRACK_CHANGED_FILE_NAME: unicode2ascii((char *) state_m->info.name, (const char *) ai_async_cmd_out_PtrArrayU8(), Min(ai_async_cmd_out_SizeArrayU8(), STR_MAX_LENGTH*2)); ai_async_audio_nav_file_info_artist(); state_m->state = STATE_TRACK_CHANGED_ARTIST; break; // Record artist metadata and call title metadata. case STATE_TRACK_CHANGED_ARTIST: unicode2ascii((char *) state_m->info.artist, (const char *) ai_async_cmd_out_PtrArrayU8(), Min(ai_async_cmd_out_SizeArrayU8(), STR_MAX_LENGTH*2)); ai_async_audio_nav_file_info_title(); state_m->state = STATE_TRACK_CHANGED_TITLE; break; // Record title metadata. case STATE_TRACK_CHANGED_TITLE: unicode2ascii((char *) state_m->info.title, (const char *) ai_async_cmd_out_PtrArrayU8(), Min(ai_async_cmd_out_SizeArrayU8(), STR_MAX_LENGTH*2)); #if defined(SUPPORT_EMBEDDED_COVER_ARTS) && SUPPORT_EMBEDDED_COVER_ARTS == true state_m->info.size.width = 100; state_m->info.size.height = 100; ai_async_audio_nav_file_info_image(&state_m->info.size); state_m->state = STATE_TRACK_CHANGED_IMAGE; #else ai_async_audio_ctrl_status(); state_m->state = STATE_TRACK_CHECK_RESUME; #endif break; // Record image data. case STATE_TRACK_CHANGED_IMAGE: state_m->info.image_data = (void *) ai_async_cmd_out_u32(); ai_async_audio_ctrl_status(); state_m->state = STATE_TRACK_CHECK_RESUME; break; // Resume the track case STATE_TRACK_CHANGED_RESUME: state_m->async_cmd = false; state_m->state = state_m->recorded_state; break; // Check if the device is in pause before sending a ai_async_audio_ctrl_resume() // command. case STATE_TRACK_CHECK_RESUME: player_flag_temp.all = ai_async_cmd_out_u32(); if (player_flag_temp.status == PLAYER_FLAG_PAUSE) ai_async_audio_ctrl_resume(); state_m->state = STATE_TRACK_CHANGED_RESUME; break; default: return; } // Error management if (state_m->cmd_status == false) state_m->state = STATE_DEVICE_DISCONNECTED; }
static void navigation_task(struct state_machine_context *state_m) { static size_t item_updated; static uint16_t temp_cursor_pos; size_t i; // By default, the command executed is asynchronous. state_m->async_cmd = true; state_m->view = GUI_UPDATE_VIEW_NAVIGATION; switch (state_m->state) { // This state id the entry point of the navigation view. // It must be call on every access to this view. case STATE_NAVIGATION_ENTRY_POINT: state_m->view_elt = GUI_UPDATE_ELT_NAVIGATION_CURSOR; state_m->async_cmd = false; state_m->cmd_status = true; // Update file_list relatives info. state_m->list.file_pos = 0; state_m->list.nb_files = 0xFFFF; state_m->list.nb_valid_entries = 0; temp_cursor_pos = 0; state_m->cursor_pointer = 0; // Invalidate all the items on the list for (i=0; i<MAX_BUFFER_FILE; i++) state_m->list.list[i].updated = false; state_m->state = STATE_NAVIGATION_UPDATE_LIST; break; // Update the file list from the current directory. case STATE_NAVIGATION_UPDATE_LIST: // Re-center the file list. if (temp_cursor_pos < state_m->list.file_pos && state_m->list.nb_valid_entries) { // Scroll-down the list memmove((void *) &state_m->list.list[1], (const void *) &state_m->list.list[0], sizeof(state_m->list.list[0])*(MAX_BUFFER_FILE - 1)); // Every element of the list have to be updated for (i=1; i<MAX_BUFFER_FILE; i++) state_m->list.list[i].updated = true; // Get information of the file. item_updated = 0; state_m->list.file_pos--; state_m->list.nb_valid_entries--; ai_async_nav_file_goto(state_m->list.file_pos + item_updated); state_m->view_elt |= GUI_UPDATE_ELT_IN_PROGRESS; state_m->state = STATE_NAVIGATION_UPDATE_LIST_GET_NAME; break; } if (temp_cursor_pos > state_m->list.file_pos && state_m->list.nb_valid_entries) { // Scroll-up the list memmove((void *) &state_m->list.list[0], (const void *) &state_m->list.list[1], sizeof(state_m->list.list[0])*(MAX_BUFFER_FILE - 1)); // Every element of the list have to be updated for (i=0; i<MAX_BUFFER_FILE-1; i++) state_m->list.list[i].updated = true; // Get information of the file. item_updated = MAX_BUFFER_FILE - 1; state_m->list.file_pos++; state_m->list.nb_valid_entries--; ai_async_nav_file_goto(state_m->list.file_pos + item_updated); state_m->view_elt |= GUI_UPDATE_ELT_IN_PROGRESS; state_m->state = STATE_NAVIGATION_UPDATE_LIST_GET_NAME; break; } // There is nothing to update state_m->async_cmd = false; state_m->view_elt |= GUI_UPDATE_ELT_IN_PROGRESS; state_m->state = STATE_NAVIGATION_WAIT_FOR_EVENT; break; // Read the file name of the file selected. case STATE_NAVIGATION_UPDATE_LIST_GET_NAME: // The case when there is no more files... if (state_m->cmd_status == false) { state_m->list.nb_files = state_m->list.file_pos + item_updated; // If no files/folders are found in the current directory... if (!state_m->list.nb_files) state_m->view_elt |= GUI_UPDATE_ELT_NAVIGATION_NO_FILES; state_m->cmd_status = true; state_m->async_cmd = false; navigation_update_view(state_m); state_m->state = STATE_NAVIGATION_WAIT_FOR_EVENT; break; } ai_async_nav_file_name(); state_m->view_elt |= GUI_UPDATE_ELT_IN_PROGRESS; state_m->state = STATE_NAVIGATION_UPDATE_LIST_STORE_NAME; break; // Store the file name of the selected file. case STATE_NAVIGATION_UPDATE_LIST_STORE_NAME: unicode2ascii((char *) state_m->list.list[item_updated].file_name, (const char *) ai_async_cmd_out_PtrArrayU8(), Min(ai_async_cmd_out_SizeArrayU8(), STR_MAX_LENGTH*2)); ai_async_nav_file_isdir(); state_m->view_elt |= GUI_UPDATE_ELT_IN_PROGRESS; state_m->state = STATE_NAVIGATION_UPDATE_ISDIR; break; // Check if the selected file is a directory or not. case STATE_NAVIGATION_UPDATE_ISDIR: state_m->list.list[item_updated].type = (ai_async_cmd_out_u32())?FILE_TYPE_DIRECTORY:FILE_TYPE_FILE; state_m->list.list[item_updated].updated = true; state_m->list.nb_valid_entries++; navigation_update_view(state_m); state_m->async_cmd = false; state_m->view_elt |= GUI_UPDATE_ELT_IN_PROGRESS; state_m->state = STATE_NAVIGATION_UPDATE_LIST; break; // This state is the "idle" state of this view. case STATE_NAVIGATION_WAIT_FOR_EVENT: // Catch new track event state_m->cmd_status = true; if (state_m->player_status.flags.new_file_played) { state_m->async_cmd = false; state_m->player_status.flags.new_file_played = 0; state_m->recorded_state = STATE_NAVIGATION_WAIT_FOR_EVENT; state_m->state = STATE_TRACK_CHANGED_ENTRY_POINT; break; } // Switch to playback view else if (controller_switch_to_playback_view(GUI_UPDATE_VIEW_NAVIGATION)) { controller_clear(); state_m->async_cmd = false; state_m->state = STATE_PLAYBACK_ENTRY_POINT; break; } // Switch to configuration view else if (controller_switch_to_config_view(GUI_UPDATE_VIEW_NAVIGATION)) { controller_clear(); state_m->async_cmd = false; state_m->state = STATE_CONFIG_ENTRY_POINT; break; } // Go up in the file list. else if (controller_navigation_cursor_previous() && temp_cursor_pos) { state_m->async_cmd = false; temp_cursor_pos--; state_m->state = STATE_NAVIGATION_UPDATE_LIST; break; } // Go down in the file list. else if (controller_navigation_cursor_next() && (temp_cursor_pos + 1 < state_m->list.file_pos + state_m->list.nb_valid_entries)) { state_m->async_cmd = false; temp_cursor_pos++; state_m->state = STATE_NAVIGATION_UPDATE_LIST; break; } // Enter directory of play the file. else if (controller_navigation_change_directory()) { if (navigation_get_current_file_type(state_m) == FILE_TYPE_FILE) { ai_async_nav_file_goto(temp_cursor_pos); state_m->state = STATE_NAVIGATION_PLAY_SELECTED_FILE; break; } else { ai_async_nav_file_goto(temp_cursor_pos); state_m->state = STATE_NAVIGATION_CD; break; } } // Go to parent directory. else if (controller_navigation_go_to_parent_directory()) { ai_async_nav_file_goto(temp_cursor_pos); state_m->state = STATE_NAVIGATION_GOTOPARENT; break; } // Play the file or the directory. else if (controller_navigation_play()) { ai_async_nav_file_goto(temp_cursor_pos); state_m->state = STATE_NAVIGATION_PLAY_SELECTED_FILE; break; } // Fill the file list with valid data. else if (state_m->list.nb_valid_entries < MAX_BUFFER_FILE && state_m->list.file_pos + state_m->list.nb_valid_entries < state_m->list.nb_files) { item_updated = state_m->list.nb_valid_entries; ai_async_nav_file_goto(state_m->list.file_pos + state_m->list.nb_valid_entries); state_m->view_elt |= GUI_UPDATE_ELT_IN_PROGRESS; state_m->state = STATE_NAVIGATION_UPDATE_LIST_GET_NAME; break; } state_m->async_cmd = false; state_m->state = STATE_CHECK_DEVICE_ENTRY_POINT; state_m->recorded_state = STATE_NAVIGATION_WAIT_FOR_EVENT; break; // Enter directory. case STATE_NAVIGATION_CD: ai_async_nav_dir_cd(); state_m->state = STATE_NAVIGATION_ENTRY_POINT; break; // Go to parent directory. case STATE_NAVIGATION_GOTOPARENT: state_m->cmd_status = true; ai_async_nav_dir_gotoparent(); state_m->state = STATE_NAVIGATION_GOTOPARENT_ERROR_HANDLING; break; // This state handle a gotoparent error. case STATE_NAVIGATION_GOTOPARENT_ERROR_HANDLING: state_m->async_cmd = false; if (state_m->cmd_status == false) state_m->state = STATE_NAVIGATION_WAIT_FOR_EVENT; else state_m->state = STATE_NAVIGATION_ENTRY_POINT; state_m->cmd_status = true; break; // This states play the file selected by the cursor. case STATE_NAVIGATION_PLAY_SELECTED_FILE: if (state_m->cmd_status) ai_async_audio_nav_playfile(); else { state_m->cmd_status = true; state_m->async_cmd = false; state_m->state = STATE_NAVIGATION_ENTRY_POINT; break; } state_m->state = STATE_NAVIGATION_WAIT_FOR_SELECTION; break; // This states makes sure the file has been selected case STATE_NAVIGATION_WAIT_FOR_SELECTION: // If we were not able to play the selected song, then play any song if (!state_m->cmd_status) { state_m->cmd_status = true; state_m->state = STATE_COMMAND_PLAY_ANY_SONG; } else state_m->state = STATE_CHECK_DEVICE_ENTRY_POINT; state_m->recorded_state = STATE_NAVIGATION_UPDATE_METADATA_AND_PLAY; state_m->async_cmd = false; break; // This state update the status of the audio player. case STATE_NAVIGATION_UPDATE_METADATA_AND_PLAY: state_m->async_cmd = false; state_m->player_status.flags.new_file_played = 0; state_m->recorded_state = STATE_PLAYBACK_ENTRY_POINT; state_m->state = STATE_TRACK_CHANGED_ENTRY_POINT; break; default: return; } // Error management. if (state_m->cmd_status == false) state_m->state = STATE_NAVIGATION_WAIT_FOR_EVENT; }