Esempio n. 1
0
/*
 * Set the current buffer to the given buffer number if it exists.
 */
static void controller_set_current_buffer(unsigned int num) {
	if (GCon.buffers[num] != NULL) {
		bufstack_swap(current_buf_num, num);
		current_buf_num = num;
		current_buf = GCon.buffers[num];
	}

	controller_clear(current_buf_num);
	buffer_redraw(current_buf);
}
Esempio n. 2
0
void rtc_init_qt( void ) {
  // Init touch_states
  controller_clear();

  // Disable all interrupts
  Disable_global_interrupt();

  // Register the RTC interrupt handler to the interrupt controller.
  BSP_INTC_IntReg( &rtc_irq, AVR32_RTC_IRQ, AVR32_INTC_INT1);

  // Initialize the RTC
  rtc_init(&AVR32_RTC, RTC_OSC_32KHZ, 4);

  rtc_set_top_value(&AVR32_RTC, 1);
  // Enable the interrupts
  rtc_enable_interrupt(&AVR32_RTC);

  // Enable the RTC
  rtc_enable(&AVR32_RTC);

  // Enable global interrupts
  Enable_global_interrupt();

}
Esempio n. 3
0
int main(int argc, char *argv[])
{
    int rc = -1, n, priority;
    const char *importer, *scanner, *geo;
    char *endptr;
    size_t nctl;
    double speed;
    struct timecode_def *timecode;
    bool protect, use_mlock, phono;

    struct controller ctl[2];
    struct rt rt;
    struct library library;

#if defined WITH_OSS || WITH_ALSA
    int rate;
#endif

#ifdef WITH_OSS
    int oss_buffers, oss_fragment;
#endif

#ifdef WITH_ALSA
    int alsa_buffer;
#endif

    fprintf(stderr, "%s\n\n" NOTICE "\n\n", banner);

    if (thread_global_init() == -1)
        return -1;

    if (rig_init() == -1)
        return -1;
    rt_init(&rt);
    library_init(&library);

    ndeck = 0;
    geo = "";
    nctl = 0;
    priority = DEFAULT_PRIORITY;
    importer = DEFAULT_IMPORTER;
    scanner = DEFAULT_SCANNER;
    timecode = NULL;
    speed = 1.0;
    protect = false;
    phono = false;
    use_mlock = false;

#if defined WITH_OSS || WITH_ALSA
    rate = DEFAULT_RATE;
#endif

#ifdef WITH_ALSA
    alsa_buffer = DEFAULT_ALSA_BUFFER;
#endif

#ifdef WITH_OSS
    oss_fragment = DEFAULT_OSS_FRAGMENT;
    oss_buffers = DEFAULT_OSS_BUFFERS;
#endif

    /* Skip over command name */

    argv++;
    argc--;

    while (argc > 0) {

        if (!strcmp(argv[0], "-h")) {
            usage(stdout);
            return 0;

#ifdef WITH_OSS
        } else if (!strcmp(argv[0], "-f")) {

            /* Set fragment size for subsequent devices */

            if (argc < 2) {
                fprintf(stderr, "-f requires an integer argument.\n");
                return -1;
            }

            oss_fragment = strtol(argv[1], &endptr, 10);
            if (*endptr != '\0') {
                fprintf(stderr, "-f requires an integer argument.\n");
                return -1;
            }

            /* Fragment sizes greater than the default aren't useful
             * as they are dependent on DEVICE_FRAME */

            if (oss_fragment < DEFAULT_OSS_FRAGMENT) {
                fprintf(stderr, "Fragment size must be %d or more; aborting.\n",
                        DEFAULT_OSS_FRAGMENT);
                return -1;
            }

            argv += 2;
            argc -= 2;

        } else if (!strcmp(argv[0], "-b")) {

            /* Set number of buffers for subsequent devices */

            if (argc < 2) {
                fprintf(stderr, "-b requires an integer argument.\n");
                return -1;
            }

            oss_buffers = strtol(argv[1], &endptr, 10);
            if (*endptr != '\0') {
                fprintf(stderr, "-b requires an integer argument.\n");
                return -1;
            }

            argv += 2;
            argc -= 2;
#endif

#if defined WITH_OSS || WITH_ALSA
        } else if (!strcmp(argv[0], "-r")) {

            /* Set sample rate for subsequence devices */

            if (argc < 2) {
                fprintf(stderr, "-r requires an integer argument.\n");
                return -1;
            }

            rate = strtol(argv[1], &endptr, 10);
            if (*endptr != '\0') {
                fprintf(stderr, "-r requires an integer argument.\n");
                return -1;
            }

            argv += 2;
            argc -= 2;
#endif

#ifdef WITH_ALSA
        } else if (!strcmp(argv[0], "-m")) {

            /* Set size of ALSA buffer for subsequence devices */

            if (argc < 2) {
                fprintf(stderr, "-m requires an integer argument.\n");
                return -1;
            }

            alsa_buffer = strtol(argv[1], &endptr, 10);
            if (*endptr != '\0') {
                fprintf(stderr, "-m requires an integer argument.\n");
                return -1;
            }

            argv += 2;
            argc -= 2;
#endif

        } else if (!strcmp(argv[0], "-d") || !strcmp(argv[0], "-a") ||
                   !strcmp(argv[0], "-j"))
        {
            int r;
            unsigned int sample_rate;
            struct deck *ld;
            struct device *device;
            struct timecoder *timecoder;

            /* Create a deck */

            if (argc < 2) {
                fprintf(stderr, "-%c requires a device name as an argument.\n",
                        argv[0][1]);
                return -1;
            }

            if (ndeck == ARRAY_SIZE(deck)) {
                fprintf(stderr, "Too many decks; aborting.\n");
                return -1;
            }

            fprintf(stderr, "Initialising deck %zd (%s)...\n", ndeck, argv[1]);

            ld = &deck[ndeck];
            device = &ld->device;
            timecoder = &ld->timecoder;
            ld->importer = importer;
            ld->protect = protect;

            /* Work out which device type we are using, and initialise
             * an appropriate device. */

            switch(argv[0][1]) {

#ifdef WITH_OSS
            case 'd':
                r = oss_init(device, argv[1], rate, oss_buffers, oss_fragment);
                break;
#endif
#ifdef WITH_ALSA
            case 'a':
                r = alsa_init(device, argv[1], rate, alsa_buffer);
                break;
#endif
#ifdef WITH_JACK
            case 'j':
                r = jack_init(device, argv[1]);
                break;
#endif
            default:
                fprintf(stderr, "Device type is not supported by this "
                        "distribution of xwax.\n");
                return -1;
            }

            if (r == -1)
                return -1;

            sample_rate = device_sample_rate(device);

            /* Default timecode decoder where none is specified */

            if (timecode == NULL) {
                timecode = timecoder_find_definition(DEFAULT_TIMECODE);
                assert(timecode != NULL);
            }

            timecoder_init(timecoder, timecode, speed, sample_rate, phono);

            /* Connect up the elements to make an operational deck */

            r = deck_init(ld, &rt, ndeck);
            if (r == -1)
                return -1;

            /* Connect this deck to available controllers */

            for (n = 0; n < nctl; n++)
                controller_add_deck(&ctl[n], &deck[ndeck]);

            /* Connect this deck to OSC server */

            osc_add_deck();

            ndeck++;

            argv += 2;
            argc -= 2;

        } else if (!strcmp(argv[0], "-t")) {

            /* Set the timecode definition to use */

            if (argc < 2) {
                fprintf(stderr, "-t requires a name as an argument.\n");
                return -1;
            }

            timecode = timecoder_find_definition(argv[1]);
            if (timecode == NULL) {
                fprintf(stderr, "Timecode '%s' is not known.\n", argv[1]);
                return -1;
            }

            argv += 2;
            argc -= 2;

        } else if (!strcmp(argv[0], "-33")) {

            speed = 1.0;

            argv++;
            argc--;

        } else if (!strcmp(argv[0], "-45")) {

            speed = 1.35;

            argv++;
            argc--;

        } else if (!strcmp(argv[0], "-c")) {

            protect = true;

            argv++;
            argc--;

        } else if (!strcmp(argv[0], "-u")) {

            protect = false;

            argv++;
            argc--;

        } else if (!strcmp(argv[0], "--line")) {

            phono = false;

            argv++;
            argc--;

        } else if (!strcmp(argv[0], "--phono")) {

            phono = true;

            argv++;
            argc--;

        } else if (!strcmp(argv[0], "-k")) {

            use_mlock = true;
            track_use_mlock();

            argv++;
            argc--;

        } else if (!strcmp(argv[0], "-q")) {

            if (argc < 2) {
                fprintf(stderr, "-q requires an integer argument.\n");
                return -1;
            }

            priority = strtol(argv[1], &endptr, 10);
            if (*endptr != '\0') {
                fprintf(stderr, "-q requires an integer argument.\n");
                return -1;
            }

            if (priority < 0) {
                fprintf(stderr, "Priority (%d) must be zero or positive.\n",
                        priority);
                return -1;
            }

            argv += 2;
            argc -= 2;

        } else if (!strcmp(argv[0], "-g")) {

            if (argc < 2) {
                fprintf(stderr, "-g requires an argument.\n");
                return -1;
            }

            geo = argv[1];

            argv += 2;
            argc -= 2;

        } else if (!strcmp(argv[0], "-i")) {

            /* Importer script for subsequent decks */

            if (argc < 2) {
                fprintf(stderr, "-i requires an executable path "
                        "as an argument.\n");
                return -1;
            }

            importer = argv[1];

            argv += 2;
            argc -= 2;

        } else if (!strcmp(argv[0], "-s")) {

            /* Scan script for subsequent libraries */

            if (argc < 2) {
                fprintf(stderr, "-s requires an executable path "
                        "as an argument.\n");
                return -1;
            }

            scanner = argv[1];

            argv += 2;
            argc -= 2;

        } else if (!strcmp(argv[0], "-l")) {

            /* Load in a music library */

            if (argc < 2) {
                fprintf(stderr, "-%c requires a pathname as an argument.\n",
                        argv[0][1]);
                return -1;
            }

            if (library_import(&library, scanner, argv[1]) == -1)
                return -1;

            argv += 2;
            argc -= 2;

#ifdef WITH_ALSA
        } else if (!strcmp(argv[0], "--dicer")) {

            struct controller *c;

            if (nctl == sizeof ctl) {
                fprintf(stderr, "Too many controllers; aborting.\n");
                return -1;
            }

            c = &ctl[nctl];

            if (argc < 2) {
                fprintf(stderr, "Dicer requires an ALSA device name.\n");
                return -1;
            }

            if (dicer_init(c, &rt, argv[1]) == -1)
                return -1;

            nctl++;

            argv += 2;
            argc -= 2;
#endif

        } else {
            fprintf(stderr, "'%s' argument is unknown; try -h.\n", argv[0]);
            return -1;
        }
    }

#ifdef WITH_ALSA
    alsa_clear_config_cache();
#endif

    if (ndeck == 0) {
        fprintf(stderr, "You need to give at least one audio device to use "
                "as a deck; try -h.\n");
        return -1;
    }

    rc = EXIT_FAILURE; /* until clean exit */

    if (osc_start((struct deck *)&deck, &library) == -1)
        return -1;
    osc_start_updater_thread();

    /* Order is important: launch realtime thread first, then mlock.
     * Don't mlock the interface, use sparingly for audio threads */

    if (rt_start(&rt, priority) == -1)
        return -1;

    if (use_mlock && mlockall(MCL_CURRENT) == -1) {
        perror("mlockall");
        goto out_rt;
    }

    if (interface_start(&library, geo) == -1)
        goto out_rt;

    if (rig_main() == -1)
        goto out_interface;

    rc = EXIT_SUCCESS;
    fprintf(stderr, "Exiting cleanly...\n");

out_interface:
    interface_stop();
out_rt:
    rt_stop(&rt);

    for (n = 0; n < ndeck; n++)
        deck_clear(&deck[n]);

    for (n = 0; n < nctl; n++)
        controller_clear(&ctl[n]);

    timecoder_free_lookup();
    library_clear(&library);
    rt_clear(&rt);
    rig_clear();
    osc_stop();
    thread_global_clear();

    if (rc == EXIT_SUCCESS)
        fprintf(stderr, "Done.\n");

    return rc;
}
Esempio n. 4
0
void controller_init(uint32_t fcpu_hz, uint32_t fhsb_hz, uint32_t fpbb_hz, uint32_t fpba_hz) {
  static const gpio_map_t QT60168_SPI_GPIO_MAP = { { QT60168_SPI_SCK_PIN,
      QT60168_SPI_SCK_FUNCTION }, // SPI Clock.
      { QT60168_SPI_MISO_PIN, QT60168_SPI_MISO_FUNCTION }, // MISO.
      { QT60168_SPI_MOSI_PIN, QT60168_SPI_MOSI_FUNCTION }, // MOSI.
      { QT60168_SPI_NPCS0_PIN, QT60168_SPI_NPCS0_FUNCTION } // Chip Select NPCS.
  };

  // SPI options.
  spi_options_t spiOptions = {
      .reg = QT60168_SPI_NCPS,
      .baudrate = QT60168_SPI_MASTER_SPEED, // Defined in conf_qt60168.h.
      .bits = QT60168_SPI_BITS, // Defined in conf_qt60168.h.
      .spck_delay = 0, .trans_delay = 0, .stay_act = 0, .spi_mode = 3,
      .modfdis = 1 };

  // Assign I/Os to SPI.
  gpio_enable_module(QT60168_SPI_GPIO_MAP, sizeof(QT60168_SPI_GPIO_MAP)
      / sizeof(QT60168_SPI_GPIO_MAP[0]));

  // Set selection mode: variable_ps, pcs_decode, delay.
  spi_selectionMode(QT60168_SPI, 0, 0, 0);

  // Enable SPI.
  spi_enable(QT60168_SPI);

  // Initialize QT60168 with SPI clock Osc0.
  spi_setupChipReg(QT60168_SPI, &spiOptions, fpba_hz);

  // Initialize QT60168 component.
  qt60168_init(fpba_hz);

  // Init timer to get key value.
  rtc_init_qt();

  // Invalidate the timeout already
  cpu_set_timeout(0, &cpu_time_clear_wheel);
}

void rtc_init_qt( void ) {
  // Init touch_states
  controller_clear();

  // Disable all interrupts
  cpu_irq_disable();

  // Register the RTC interrupt handler to the interrupt controller.
  irq_register_handler(rtc_irq, AVR32_RTC_IRQ, 0);

  // Initialize the RTC
  rtc_init(&AVR32_RTC, RTC_OSC_32KHZ, 4);

  rtc_set_top_value(&AVR32_RTC, 1);
  // Enable the interrupts
  rtc_enable_interrupt(&AVR32_RTC);

  // Enable the RTC
  rtc_enable(&AVR32_RTC);

  // Enable global interrupts
  cpu_irq_enable();

}
Esempio n. 5
0
static void config_task(struct state_machine_context *state_m)
{
  // By default, the command executed is asynchronous.
  state_m->async_cmd = true;
  state_m->view = GUI_UPDATE_VIEW_CONFIG;

  switch (state_m->state)
  {
  // This state id the entry point of the configuration view.
  // It must be call on every access to this view.
  case STATE_CONFIG_ENTRY_POINT:
    state_m->view_elt = GUI_UPDATE_ELT_NONE;
    state_m->view_elt |= GUI_UPDATE_ELT_CONFIG_CURSOR;
    state_m->cmd_status = true;
    state_m->async_cmd = false;
    state_m->display_list.mode_pos = MODE_POS_REPEAT;
    state_m->state = STATE_CONFIG_UPDATE_STATES;
    break;
  // This state is the "idle" state of this view.
  case STATE_CONFIG_WAIT_FOR_EVENT:
    // Switch to navigation view
    if (controller_switch_to_navigation_view(GUI_UPDATE_VIEW_CONFIG))
    {
      controller_clear();
      state_m->async_cmd = false;
      state_m->state = STATE_NAVIGATION_ENTRY_POINT;
      break;
    }
    else if (controller_switch_to_playback_view(GUI_UPDATE_VIEW_CONFIG))
    {
      controller_clear();
      state_m->async_cmd = false;
      state_m->state = STATE_PLAYBACK_ENTRY_POINT;
      break;
    }
    else if (controller_config_change_mode())
    {
      switch (state_m->display_list.mode_pos)
      {
      case MODE_POS_SHUFFLE:
        switch (state_m->player_status.shuffle)
        {
        case AUDIO_SHUFFLE_FOLDER:
          ai_async_audio_nav_shuffle_set(AUDIO_SHUFFLE_ALL);
          break;
        case AUDIO_SHUFFLE_ALL:
          ai_async_audio_nav_shuffle_set(AUDIO_SHUFFLE_OFF);
          break;
        case AUDIO_SHUFFLE_OFF:
        default:
          ai_async_audio_nav_shuffle_set(AUDIO_SHUFFLE_FOLDER);
        }
        break;
      case MODE_POS_REPEAT:
        switch (state_m->player_status.repeat)
        {
        case AUDIO_REPEAT_TRACK:
          ai_async_audio_nav_repeat_set(AUDIO_REPEAT_FOLDER);
          break;
        case AUDIO_REPEAT_FOLDER:
          ai_async_audio_nav_repeat_set(AUDIO_REPEAT_ALL);
          break;
        case AUDIO_REPEAT_ALL:
          ai_async_audio_nav_repeat_set(AUDIO_REPEAT_OFF);
          break;
        case AUDIO_REPEAT_OFF:
        default:
          ai_async_audio_nav_repeat_set(AUDIO_REPEAT_TRACK);
        }
        break;
      }
      state_m->state = STATE_CONFIG_UPDATE_STATES;
      break;
    }
    else if (controller_config_next_option())
    {
      state_m->async_cmd = false;
      switch (state_m->display_list.mode_pos)
      {
      case MODE_POS_REPEAT:
        state_m->display_list.mode_pos = MODE_POS_SHUFFLE;
        break;
      case MODE_POS_SHUFFLE:
      default:
        state_m->display_list.mode_pos = MODE_POS_REPEAT;
      }
      state_m->view_elt |= GUI_UPDATE_ELT_CONFIG_CURSOR;
      break;
    }
    else if (controller_config_previous_option())
    {
      state_m->async_cmd = false;
      switch (state_m->display_list.mode_pos)
      {
      case MODE_POS_REPEAT:
        state_m->display_list.mode_pos = MODE_POS_SHUFFLE;
        break;
      case MODE_POS_SHUFFLE:
      default:
        state_m->display_list.mode_pos = MODE_POS_REPEAT;
      }
      state_m->view_elt |= GUI_UPDATE_ELT_CONFIG_CURSOR;
      break;
    }
    state_m->async_cmd = false;
    break;
  // Get repeat states.
  case STATE_CONFIG_UPDATE_STATES:
    ai_async_audio_nav_repeat_get();
    state_m->state = STATE_CONFIG_READ_REPEAT_STATE;
    break;
  // Get shuffle states.
  case STATE_CONFIG_READ_REPEAT_STATE:
    state_m->player_status.repeat = ai_async_cmd_out_u32();
    state_m->view_elt |= GUI_UPDATE_ELT_CONFIG_REPEAT;
    ai_async_audio_nav_shuffle_get();
    state_m->state = STATE_CONFIG_READ_SHUFFLE_STATE;
    break;
  // Read shuffle states.
  case STATE_CONFIG_READ_SHUFFLE_STATE:
    state_m->player_status.shuffle = ai_async_cmd_out_u32();
    state_m->view_elt |= GUI_UPDATE_ELT_CONFIG_SHUFFLE;
    state_m->state = STATE_CONFIG_WAIT_FOR_EVENT;
    break;
  default:
    return;
  }

  // Error management
  if (state_m->cmd_status == false)
    state_m->state = STATE_CONFIG_ENTRY_POINT;
}
Esempio n. 6
0
static void playback_task(struct state_machine_context *state_m)
{
  static enum
  {
    PLAYER_STATUS_NOT_DEFINED,
    PLAYER_STATUS_PLAY,
    PLAYER_STATUS_PAUSE,
    PLAYER_STATUS_STOP,
    PLAYER_STATUS_FFW,
    PLAYER_STATUS_FRW
  } current_view_player_status;
  static bool fast_mode = false;

  // By default, the command executed is asynchronous.
  state_m->async_cmd = true;
  state_m->view = GUI_UPDATE_VIEW_PLAYBACK;

  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_PLAYBACK_ENTRY_POINT:
    state_m->view_elt = GUI_UPDATE_ELT_NONE;
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_ELAPSED_TIME;
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_VOLUME;
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_ARTIST;
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_TITLE;
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_FILE_NAME;
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_TOTAL_TIME;
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_COVER_ART;
    state_m->cmd_status = true;
    state_m->async_cmd = false;
    state_m->info.volume = audio_mixer_dacs_get_volume();
    current_view_player_status = PLAYER_STATUS_NOT_DEFINED;
    cpu_set_timeout(cpu_ms_2_cy(ELAPSED_TIME_TIMER_VALUE_MS, FCPU_HZ), &state_m->elapsed_time_timer);
    state_m->state = STATE_PLAYBACK_WAIT_FOR_EVENT;
    break;
  // This state is the "idle" state of this view.
  case STATE_PLAYBACK_WAIT_FOR_EVENT:
    // Catch new track event
    if (state_m->player_status.flags.new_file_played)
    {
      // Notify the controller a new track is being played
      controller_playback_ffw(true);
      controller_playback_frw(true);
      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;
    }
    // Switch to navigation view
    else if (controller_switch_to_navigation_view(GUI_UPDATE_VIEW_PLAYBACK))
    {
      controller_clear();
      state_m->async_cmd = false;
      state_m->state = STATE_NAVIGATION_ENTRY_POINT;
      break;
    }
    // Switch to configuration view
    else if (controller_switch_to_config_view(GUI_UPDATE_VIEW_PLAYBACK))
    {
      controller_clear();
      state_m->async_cmd = false;
      state_m->state = STATE_CONFIG_ENTRY_POINT;
      break;
    }
    // Increase volume
    else if (controller_playback_increase_volume())
    {
      state_m->async_cmd = false;
      audio_mixer_dacs_increase_volume();
      audio_mixer_dacs_increase_volume();
      state_m->info.volume = audio_mixer_dacs_get_volume();
      state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_VOLUME;
      break;
    }
    // Decrease volume
    else if (controller_playback_decrease_volume())
    {
      state_m->async_cmd = false;
      audio_mixer_dacs_decrease_volume();
      audio_mixer_dacs_decrease_volume();
      state_m->info.volume = audio_mixer_dacs_get_volume();
      state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_VOLUME;
      break;
    }
    else if (controller_playback_ffw(false))
    {
      ai_async_audio_ctrl_start_ffw();
      state_m->state = STATE_CHECK_DEVICE_ENTRY_POINT;
      state_m->recorded_state = STATE_PLAYBACK_HANDLE_FAST_MODES;
      fast_mode = true;
      break;
    }
    else if (controller_playback_frw(false))
    {
      ai_async_audio_ctrl_start_frw();
      state_m->state = STATE_CHECK_DEVICE_ENTRY_POINT;
      state_m->recorded_state = STATE_PLAYBACK_HANDLE_FAST_MODES;
      fast_mode = true;
      break;
    }
    else if (fast_mode)
    {
      ai_async_audio_ctrl_stop_ffw_frw();
      state_m->state = STATE_CHECK_DEVICE_ENTRY_POINT;
      state_m->recorded_state = STATE_PLAYBACK_HANDLE_FAST_MODES;
      fast_mode = false;
      break;
    }
    // Previous track
    else if (controller_playback_previous_track())
    {
      ai_async_audio_nav_previous();
      break;
    }
    // Next track
    else if (controller_playback_next_track())
    {
      ai_async_audio_nav_next();
      break;
    }
    // Toggle play/pause
    else if (controller_playback_toggle_play_pause())
    {
      switch (state_m->player_status.flags.status)
      {
      case PLAYER_FLAG_PLAY:
        ai_async_audio_ctrl_pause();
        state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_PAUSE;
        break;
      case PLAYER_FLAG_PAUSE:
        ai_async_audio_ctrl_resume();
        state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_PLAY;
        break;
      case PLAYER_FLAG_STOP:
        ai_async_audio_nav_playfile();
        state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_PLAY;
        break;
      }
      break;
    }
    else if (cpu_is_timeout(&state_m->elapsed_time_timer))
    {
      cpu_set_timeout(cpu_ms_2_cy(ELAPSED_TIME_TIMER_VALUE_MS, FCPU_HZ), &state_m->elapsed_time_timer);
      ai_async_audio_ctrl_time();
      state_m->state = STATE_PLAYBACK_UPDATE_TIME;
      break;
    }
    state_m->async_cmd = false;
    state_m->state = STATE_CHECK_DEVICE_ENTRY_POINT;
    state_m->recorded_state = STATE_PLAYBACK_UPDATE_STATUS;
    break;
  // This state is called after fats forward or fast rewind commands to handle return states.
  case STATE_PLAYBACK_HANDLE_FAST_MODES:
    cpu_set_timeout(cpu_ms_2_cy(ELAPSED_TIME_TIMER_VALUE_MS, FCPU_HZ), &state_m->elapsed_time_timer);
    ai_async_audio_ctrl_time();
    state_m->state = STATE_PLAYBACK_UPDATE_TIME;
    break;
  // This state update the elapsed time of the current track being played.
  case STATE_PLAYBACK_UPDATE_TIME:
    state_m->async_cmd = false;
    state_m->info.elapsed_time = ai_async_cmd_out_u32();
    state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_ELAPSED_TIME;
    state_m->state = STATE_PLAYBACK_WAIT_FOR_EVENT;
    break;
  // This state update the elapsed time of the current track being played.
  case STATE_PLAYBACK_UPDATE_STATUS:
    state_m->async_cmd = false;
    // Update control GUI
    if (state_m->player_status.flags.status_fast == PLAYER_FLAG_FFW &&
        current_view_player_status != PLAYER_STATUS_FFW)
      state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_FFW;
    else if (state_m->player_status.flags.status_fast == PLAYER_FLAG_FRW &&
             current_view_player_status != PLAYER_STATUS_FRW)
      state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_FRW;
    else if (state_m->player_status.flags.status == PLAYER_FLAG_PLAY &&
             current_view_player_status != PLAYER_STATUS_PLAY)
      state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_PLAY;
    else if (state_m->player_status.flags.status == PLAYER_FLAG_PAUSE &&
             current_view_player_status != PLAYER_STATUS_PAUSE)
      state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_PAUSE;
    else if (state_m->player_status.flags.status == PLAYER_FLAG_STOP &&
             current_view_player_status != PLAYER_STATUS_STOP)
      state_m->view_elt |= GUI_UPDATE_ELT_PLAYBACK_STOP;
    state_m->state = STATE_PLAYBACK_WAIT_FOR_EVENT;
    break;
  default:
    return;
  }

  // Error management
  if (state_m->cmd_status == false)
    state_m->state = STATE_PLAYBACK_WAIT_FOR_EVENT;
}
Esempio n. 7
0
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;
}