/****************************************************************************/
/*                                                                          */
/*  File Name:  audio_vm_play.c                                             */
/*                                                                          */
/*  Purpose:  This file contains all the functions used to manage the       */
/*            Voice Memorization AMR play task.                             */
/*                                                                          */
/*  Version   0.1                                                           */
/*                                                                          */
/*  Date        Modification                                                */
/*  ------------------------------------                                    */
/*  ?? ?? 2002 Create                                                       */
/*                                                                          */
/*  Author                                                                  */
/*     Stephanie Gerthoux                                                   */
/*                                                                          */
/* (C) Copyright 2001 by Texas Instruments Incorporated, All Rights Reserved*/
/****************************************************************************/

#include "rv/rv_defined_swe.h"
#ifdef RVM_AUDIO_MAIN_SWE
#ifndef _WINDOWS
    #include "config/swconfig.cfg"
    #include "config/sys.cfg"
    #include "config/chipset.cfg"
  #endif

  /* include the usefull L1 header */
  #include "l1_confg.h"

#if (L1_VOICE_MEMO_AMR)
  #include "rv/rv_general.h"
  #include "rvm/rvm_gen.h"
  #include "audio/audio_features_i.h"
  #include "audio/audio_ffs_i.h"
  #include "audio/audio_api.h"
  #include "audio/audio_structs_i.h"
  #include "audio/audio_var_i.h"
  #include "audio/audio_messages_i.h"
  #include "rvf/rvf_target.h"
  #include "audio/audio_const_i.h"
  #include "audio/audio_error_hdlr_i.h"
  #include "audio/audio_features_i.h"

  /* include the usefull L1 header */
  #define BOOL_FLAG
  #define CHAR_FLAG
  #include "l1_types.h"
  #include "l1audio_cust.h"
  #include "l1audio_msgty.h"
  #include "l1audio_signa.h"

  #include "audio/audio_macro_i.h"

  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_vm_amr_play_send_status                            */
  /*                                                                              */
  /*    Purpose:  This function sends the voice memorization AMR play status      */
  /*              to the entity.                                                  */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        status,                                                               */
  /*        return path                                                           */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
#if (AUDIO_MEM_MANAGER)
  void audio_vm_amr_play_send_status (T_AUDIO_RET status, T_RV_RETURN return_path)
  {
    T_AUDIO_AMR_PLAY_STATUS *p_send_message;
    T_RVF_MB_STATUS mb_status = RVF_RED;

    /* allocate the message buffer */
    while (mb_status == RVF_RED)
    {
      mb_status = rvf_get_buf (p_audio_gbl_var->mb_external,
                               sizeof (T_AUDIO_AMR_PLAY_STATUS),
                               (T_RVF_BUFFER **) (&p_send_message));

      /* If insufficient resources, then report a memory error and abort.               */
      /* and wait until more ressource is given */
      if (mb_status == RVF_RED)
      {
        audio_voice_memo_amr_error_trace(AUDIO_ENTITY_NO_MEMORY);
        rvf_delay(RVF_MS_TO_TICKS(1000));
      }
    }

    /*fill the header of the message */
    p_send_message->os_hdr.msg_id = AUDIO_AMR_PLAY_FROM_MEM_STATUS_MSG;

    /* fill the status parameters */
    p_send_message->status = status;

    /* send message or call callback */
    if (return_path.callback_func == NULL)
      rvf_send_msg (return_path.addr_id, p_send_message);
    else
    {
      (*return_path.callback_func)((void *)(p_send_message));
       rvf_free_buf((T_RVF_BUFFER *)p_send_message);
    }
  }

  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_vm_amr_play_from_memory_manager                    */
  /*                                                                              */
  /*    Purpose:  This function is called to manage a voice memorization play     */
  /*              manager                                                         */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        Message to the audio entity                                           */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  void audio_vm_amr_play_from_memory_manager (T_RV_HDR *p_message)
  {
    /* Declare local variables.                                                   */
    T_RV_HDR *p_send_message;
    T_RVF_MB_STATUS mb_status;
    T_RV_RETURN return_path;

    /**************** audio_vm_amr_play_from_memory_manager function begins ***********************/
    switch(p_audio_gbl_var->audio_vm_amr_play.state)
    {
      case AUDIO_IDLE:
      {
        switch(p_message->msg_id)
        {
          case AUDIO_VM_AMR_PLAY_FROM_FFS_START_REQ:
          case AUDIO_VM_AMR_PLAY_FROM_RAM_START_REQ:
          {
            T_AUDIO_DRIVER_PARAMETER driver_parameter;

            switch (p_message->msg_id)
            {
              case AUDIO_VM_AMR_PLAY_FROM_FFS_START_REQ:
              {
                /* save the return path + ffs_fd */
              #if (AUDIO_RAM_MANAGER)
                p_audio_gbl_var->audio_vm_amr_play.audio_ram_fd = NULL;
              #endif
                p_audio_gbl_var->audio_vm_amr_play.return_path.callback_func =
                  ((T_AUDIO_VM_AMR_PLAY_FROM_FFS_START *)p_message)->return_path.callback_func;
                p_audio_gbl_var->audio_vm_amr_play.return_path.addr_id   =
                  ((T_AUDIO_VM_AMR_PLAY_FROM_FFS_START*)p_message)->return_path.addr_id;
              #if (AUDIO_NEW_FFS_MANAGER)
                p_audio_gbl_var->audio_vm_amr_play.ffs_fd =
                  ((T_AUDIO_VM_AMR_PLAY_FROM_FFS_START *)p_message)->audio_ffs_fd;
              #endif
              }
              break;
              case AUDIO_VM_AMR_PLAY_FROM_RAM_START_REQ:
              {
                /* save the return path + ffs_fd */
              #if (AUDIO_NEW_FFS_MANAGER)
                p_audio_gbl_var->audio_vm_amr_play.ffs_fd = NULL;
              #endif
                p_audio_gbl_var->audio_vm_amr_play.return_path.callback_func =
                  ((T_AUDIO_VM_AMR_PLAY_FROM_RAM_START *)p_message)->return_path.callback_func;
                p_audio_gbl_var->audio_vm_amr_play.return_path.addr_id   =
                  ((T_AUDIO_VM_AMR_PLAY_FROM_RAM_START*)p_message)->return_path.addr_id;
              #if (AUDIO_RAM_MANAGER)
                p_audio_gbl_var->audio_vm_amr_play.audio_ram_fd =
                  ((T_AUDIO_VM_AMR_PLAY_FROM_RAM_START *)p_message)->p_buffer;
                p_audio_gbl_var->audio_vm_amr_play.audio_ram_size =
                  ((T_AUDIO_VM_AMR_PLAY_FROM_RAM_START *)p_message)->buffer_size;
              #endif
              }
              break;
            }

            /* driver parameters */
            driver_parameter.nb_buffer   = AUDIO_VM_AMR_PLAY_NB_BUFFER;
            driver_parameter.buffer_size = AUDIO_VM_AMR_PLAY_SIZE;// 16 bit words

            /* return_path for driver */
            return_path.callback_func    = NULL;
            return_path.addr_id          = p_audio_gbl_var->addrId;

            /* Init driver */
            audio_driver_init_vm_amr_play_session(&driver_parameter, return_path);

            p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_WAIT_CHANNEL_ID;
          }
          break;
          case AUDIO_VM_AMR_PLAY_FROM_FFS_STOP_REQ:
          case AUDIO_VM_AMR_PLAY_FROM_RAM_STOP_REQ:
          {
            audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
            /* do not send a status message because of pre-emption issues
               An automatic stop can pre-empt a stop request. A status is sent + back in state idle
               then the stop request is received and another status is sent, which can be misinterpreted */
          }
          break;
        }
      }
      break;

      case AUDIO_WAIT_CHANNEL_ID:
      {
        switch(p_message->msg_id)
        {
          case AUDIO_DRIVER_INIT_STATUS_MSG:
          {
            /* check init is successfull otherwise, send status AUDIO_ERROR */
            if (((T_AUDIO_DRIVER_INIT_STATUS *)p_message)->status == AUDIO_OK)
            {
              /* get channel id */
              p_audio_gbl_var->audio_vm_amr_play.channel_id = ((T_AUDIO_DRIVER_INIT_STATUS *)p_message)->channel_id;

              /* Send the Start message to MEM */
              mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal,
                                       sizeof (T_AUDIO_MEM_START),
                                       (T_RVF_BUFFER **) (&p_send_message));

              /* If insufficient resources, then report a memory error and abort.               */
              if (mb_status == RVF_RED)
              {
                audio_voice_memo_amr_error_trace(AUDIO_ENTITY_NO_MEMORY);
                // TODO: use blocking function from GSP
                return;
              }

              /* fill the header of the message */
              ((T_AUDIO_MEM_START *)p_send_message)->os_hdr.msg_id = AUDIO_MEM_START_REQ;

              /* fill the parameters */
              ((T_AUDIO_MEM_START *)p_send_message)->session_id = AUDIO_VM_AMR_PLAY_SESSION_ID;
              ((T_AUDIO_MEM_START *)p_send_message)->channel_id = p_audio_gbl_var->audio_vm_amr_play.channel_id;
              ((T_AUDIO_MEM_START *)p_send_message)->size = AUDIO_VM_AMR_PLAY_SIZE*2;// 8-bit
            #if (AUDIO_NEW_FFS_MANAGER)
              ((T_AUDIO_MEM_START *)p_send_message)->audio_ffs_fd = p_audio_gbl_var->audio_vm_amr_play.ffs_fd;
            #endif
            #if (AUDIO_RAM_MANAGER)
              ((T_AUDIO_MEM_START *)p_send_message)->audio_ram_fd = p_audio_gbl_var->audio_vm_amr_play.audio_ram_fd;
              ((T_AUDIO_MEM_START *)p_send_message)->audio_ram_size = p_audio_gbl_var->audio_vm_amr_play.audio_ram_size;
            #endif

              /* send the message to the entity */
              rvf_send_msg (p_audio_gbl_var->audio_ffs_addrId, p_send_message);

              /* change state */
              p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_WAIT_STOP;
            }
            else
            {
              audio_voice_memo_amr_error_trace(AUDIO_ERROR_START_EVENT);
              audio_vm_amr_play_send_status (AUDIO_ERROR,
                p_audio_gbl_var->audio_vm_amr_play.return_path);
              /* change state */
              p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_IDLE;
            }
          }
          break;
          case AUDIO_VM_AMR_PLAY_FROM_FFS_STOP_REQ:
          #if (AUDIO_RAM_MANAGER)
            if (p_audio_gbl_var->audio_vm_amr_play.audio_ram_fd != NULL)
            {
              audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
              return;
            }
          #endif
            /* change state */
            p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_WAIT_CHANNEL_ID_TO_STOP;
          break;
          case AUDIO_VM_AMR_PLAY_FROM_RAM_STOP_REQ:
          #if (AUDIO_NEW_FFS_MANAGER)
            if (p_audio_gbl_var->audio_vm_amr_play.ffs_fd != NULL)
            {
              audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
              return;
            }
          #endif
            /* change state */
            p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_WAIT_CHANNEL_ID_TO_STOP;
          break;
        }
      } // case AUDIO_WAIT_CHANNEL_ID:
      break;

      case AUDIO_WAIT_STOP:
      {
        switch (p_message->msg_id)
        {
          case AUDIO_VM_AMR_PLAY_FROM_FFS_STOP_REQ:
          case AUDIO_VM_AMR_PLAY_FROM_RAM_STOP_REQ:
          {
            // we handle a RAM stop when New_ffs is running as an error
          #if (AUDIO_NEW_FFS_MANAGER)
            if ((p_message->msg_id == AUDIO_VM_AMR_PLAY_FROM_RAM_STOP_REQ)&&
                (p_audio_gbl_var->audio_vm_amr_play.ffs_fd != NULL))
            {
              audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
              return;
            }
          #endif
          // we handle a New_ffs stop when RAM is running as an error
          #if (AUDIO_RAM_MANAGER)
            if ((p_message->msg_id == AUDIO_VM_AMR_PLAY_FROM_FFS_STOP_REQ)&&
                (p_audio_gbl_var->audio_vm_amr_play.audio_ram_fd != NULL))
            {
              audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
              return;
            }
          #endif
            /* Send the Stop message to the FFS */
            mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal,
                                     sizeof (T_AUDIO_MEM_STOP),
                                     (T_RVF_BUFFER **) (&p_send_message));

            /* If insufficient resources, then report a memory error and abort.               */
            if (mb_status == RVF_RED)
            {
              audio_voice_memo_amr_error_trace(AUDIO_ENTITY_NO_MEMORY);
              return;
            }

            /* fill message */
            ((T_AUDIO_MEM_STOP *)p_send_message)->os_hdr.msg_id = AUDIO_MEM_STOP_REQ;
            ((T_AUDIO_MEM_STOP *)p_send_message)->channel_id    = p_audio_gbl_var->audio_vm_amr_play.channel_id;

            /* send the message to the entity */
            rvf_send_msg (p_audio_gbl_var->audio_ffs_addrId, p_send_message);

            p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_WAIT_STOP_CON;
          }
          break;
          case AUDIO_MEM_STATUS_MSG:
          {
            if (((T_AUDIO_MEM_STATUS *)p_message)->status_type == AUDIO_STOP_STATUS)
            {
              /* should be useless as it is an automatic stop so AUDIO_OK */
              if (((T_AUDIO_MEM_STATUS *)p_message)->status == AUDIO_OK)
              {
                audio_vm_amr_play_send_status (AUDIO_OK,
                  p_audio_gbl_var->audio_vm_amr_play.return_path);
                p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_IDLE;
              }
            }
            if (((T_AUDIO_MEM_STATUS *)p_message)->status_type == AUDIO_START_STATUS)
            {
              /* MEM could not find a free mem channel */
              if (((T_AUDIO_MEM_STATUS *)p_message)->status == AUDIO_ERROR)
              {
                audio_vm_amr_play_send_status (AUDIO_ERROR,
                  p_audio_gbl_var->audio_vm_amr_play.return_path);
                p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_IDLE;
              }
            }
          }
          break;
        }
      }
      break;
      case AUDIO_WAIT_STOP_CON:
      {
        switch (p_message->msg_id)
        {
          case AUDIO_MEM_STATUS_MSG:
          {
            if (((T_AUDIO_MEM_STATUS *)p_message)->status_type == AUDIO_STOP_STATUS)
            {
              audio_vm_amr_play_send_status (AUDIO_OK,
                p_audio_gbl_var->audio_vm_amr_play.return_path);
              p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_IDLE;
            }
          }
          break;
          case AUDIO_VM_AMR_PLAY_FROM_FFS_STOP_REQ:
          case AUDIO_VM_AMR_PLAY_FROM_RAM_STOP_REQ:
            audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
          break;
        }
      }
      break;
      case AUDIO_WAIT_CHANNEL_ID_TO_STOP:
      {
        switch (p_message->msg_id)
        {
          case AUDIO_DRIVER_INIT_STATUS_MSG:
          {
            if (((T_AUDIO_DRIVER_INIT_STATUS *)p_message)->status == AUDIO_OK)
            {
              /* get channel_id */
              p_audio_gbl_var->audio_vm_amr_play.channel_id = ((T_AUDIO_DRIVER_INIT_STATUS *)p_message)->channel_id;

              audio_driver_stop_session(p_audio_gbl_var->audio_vm_amr_play.channel_id);

              /* change state */
              p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_WAIT_DRIVER_STOP_CON;
            }
            else
            {
              /* close file */
            #if (AUDIO_NEW_FFS_MANAGER)
              if (p_audio_gbl_var->audio_vm_amr_play.ffs_fd != NULL)
              {
                if ( ffs_close(p_audio_gbl_var->audio_vm_amr_play.ffs_fd) != EFFS_OK )
                {
                  audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE);
                }
                AUDIO_SEND_TRACE("AUDIO VM AMR PLAY: close FFS file:", RV_TRACE_LEVEL_DEBUG_LOW);
              }
            #endif

              audio_vm_amr_play_send_status (AUDIO_OK,
                p_audio_gbl_var->audio_vm_amr_play.return_path);

              /* change state */
              p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_IDLE;
            }
          }
          break;
          case AUDIO_VM_AMR_PLAY_FROM_FFS_STOP_REQ:
          case AUDIO_VM_AMR_PLAY_FROM_RAM_STOP_REQ:
            audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
          break;
        }
      } // case AUDIO_WAIT_CHANNEL_ID_TO_STOP:
      break;
      case AUDIO_WAIT_DRIVER_STOP_CON:
      {
        switch (p_message->msg_id)
        {
          case AUDIO_DRIVER_STATUS_MSG:
          {
            if (((T_AUDIO_DRIVER_STATUS *)p_message)->status_type == AUDIO_STOP_STATUS)
            {
              /* close file */
            #if (AUDIO_NEW_FFS_MANAGER)
              if (p_audio_gbl_var->audio_vm_amr_play.ffs_fd != NULL)
              {
                if ( ffs_close(p_audio_gbl_var->audio_vm_amr_play.ffs_fd) != EFFS_OK )
                {
                  audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE);
                }
                AUDIO_SEND_TRACE("AUDIO VM AMR PLAY: close FFS file", RV_TRACE_LEVEL_DEBUG_LOW);
              }
            #endif

              audio_vm_amr_play_send_status (((T_AUDIO_DRIVER_STATUS *)p_message)->status,
                p_audio_gbl_var->audio_vm_amr_play.return_path);
              p_audio_gbl_var->audio_vm_amr_play.state = AUDIO_IDLE;
            }
          }
          break;
          case AUDIO_VM_AMR_PLAY_FROM_FFS_STOP_REQ:
          case AUDIO_VM_AMR_PLAY_FROM_RAM_STOP_REQ:
            audio_voice_memo_amr_error_trace(AUDIO_ERROR_STOP_EVENT);
          break;
        }
      } //case AUDIO_WAIT_DRIVER_STOP_CON:
      break;
    }
  } /*********************** End of audio_vm_amr_play_from_memory_manager function **********************/
#endif // AUDIO_MEM_MANAGER

  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_driver_vm_amr_play_manager                         */
  /*                                                                              */
  /*    Purpose:  This function is called to manage a voice memorization AMR play */
  /*              manager                                                         */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        Message to the audio entity                                           */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  T_AUDIO_RET audio_driver_vm_amr_play_manager (T_RV_HDR *p_message, T_AUDIO_DRIVER_SESSION *p_session)
  {
    /**************** audio_driver_vm_amr_play_manager function begins ***********************/
    switch(p_session->session_info.state)
    {
      case AUDIO_DRIVER_CHANNEL_WAIT_INIT:
      {
        /* init buffer index, layer1 not valid until 1st buffer is filled */
        /* index_l1 will be set to 0 when get_play_buffer() is called in WAIT_START state */
        p_session->session_info.index_l1    = 0xFF;
        p_session->session_info.index_appli = 0;
        p_session->session_info.play_api_state = AUDIO_PLAY_API_STATE_GET_BUF;

        /* allocate the buffer for the message to the L1 */
        p_session->session_req.p_l1_send_message =
          audio_allocate_l1_message(sizeof(T_MMI_VM_AMR_PLAY_REQ));
        ((T_MMI_VM_AMR_PLAY_REQ *)(p_session->session_req.p_l1_send_message))->session_id =
          AUDIO_VM_AMR_PLAY_SESSION_ID;

        if (p_session->session_req.p_l1_send_message != NULL )
          return (AUDIO_OK);
        else
          return (AUDIO_ERROR);
      }
      break;

      case AUDIO_DRIVER_CHANNEL_WAIT_START:
      {
        /* send the start voice memo play message to the L1 */
        audio_send_l1_message(MMI_VM_AMR_PLAY_START_REQ,
                              p_session->session_req.p_l1_send_message);
        return (AUDIO_OK);
      }
      break;

      case AUDIO_DRIVER_CHANNEL_WAIT_STOP:
      {
        /* send the stop command to the audio L1 */
        void *p_send_message = audio_allocate_l1_message(0);
        if ( p_send_message != NULL)
        {
          /* send the stop command to the audio L1 */
          audio_send_l1_message(MMI_VM_AMR_PLAY_STOP_REQ, p_send_message);
          return (AUDIO_OK);
        }
        return (AUDIO_ERROR);
      }
      break;
      case AUDIO_DRIVER_CHANNEL_WAIT_START_CON_TO_STOP:
      {
        /* send the stop command to the audio L1 */
        void *p_send_message = audio_allocate_l1_message(0);
        if ( p_send_message != NULL)
        {
          /* send the stop command to the audio L1 */
          audio_send_l1_message(MMI_VM_AMR_PLAY_STOP_REQ, p_send_message);
          return (AUDIO_OK);
        }
        return (AUDIO_ERROR);
      }
      break;
    }
  } /*********************** End of audio_vm_play_manager function **********************/

#endif /* VM_AMR_PLAY */
#endif /* RVM_AUDIO_MAIN_SWE */
