view src/cs/services/audio/audio_midi.c @ 275:79cfefc1e2b4

audio mode load: gracefully handle mode files of wrong AEC version Unfortunately our change of enabling L1_NEW_AEC (which is necessary in order to bring our Calypso ARM fw into match with the underlying DSP reality) brings along a change in the audio mode file binary format and file size - all those new tunable AEC parameters do need to be stored somewhere, after all. But we already have existing mode files in the old format, and setting AEC config to garbage when loading old audio modes (which is what would happen without the present change) is not an appealing proposition. The solution implemented in the present change is as follows: the audio mode loading code checks the file size, and if it differs from the active version of T_AUDIO_MODE, the T_AUDIO_AEC_CFG structure is cleared - set to the default (disabled AEC) for the compiled type of AEC. We got lucky in that this varying T_AUDIO_AEC_CFG structure sits at the end of T_AUDIO_MODE!
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 30 Jul 2021 02:55:48 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/****************************************************************************/
/*                                                                          */
/*  File Name:  audio_midi.c	                                              */
/*                                                                          */
/*  Purpose:  This file contains all the functions used to manage MIDI      */
/*                                                                          */
/*  Version   0.1                                                           */
/*                                                                          */
/*  Date        Modification                                                */
/*  ------------------------------------                                    */
/*  11 June 2003 Create                                                     */
/*                                                                          */
/*  Author                                                                  */
/*     Fabrice Goucem                                                       */
/*                                                                          */
/* (C) Copyright 2003 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"

  #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_macro_i.h"

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


  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_midi_start                                         */
  /*                                                                              */
  /*    Purpose:  This function is called to initiate a MIDI file playback        */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        Midi file parameters,                                                 */
  /*        Return path.                                                          */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*         Validation of the MIDI parameters.                                   */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  T_AUDIO_RET audio_midi_start(T_AUDIO_MIDI_PARAMETER *parameter, T_RV_RETURN *p_return_path)
  {
    #if (L1_MIDI==1)
      // Declare local variables
      T_RVF_MB_STATUS    mb_status=RVF_GREEN;
      T_AUDIO_MIDI_START *p_msg_start=NULL;
      T_FFS_FD           ffs_fd;

      /************************ audio_midi_start function begins ******************/

      if(p_audio_gbl_var==NULL)
      {
         audio_midi_error_trace(AUDIO_ENTITY_NOT_START);
         return(AUDIO_ERROR);
      }

      // check if the midi file exists
#ifndef _WINDOWS
      ffs_fd=ffs_open(parameter->midi_name,FFS_O_RDONLY);
      if(ffs_fd<=0)
      {
        audio_midi_error_trace(AUDIO_ENTITY_FILE_ERROR);
        return(AUDIO_ERROR);
      }
#else
      ffs_fd=0xdeadbeef;
#endif // _WINDOWS

      // allocate the memory for the message to send
      mb_status=rvf_get_buf(p_audio_gbl_var->mb_external,
                            sizeof(T_AUDIO_MIDI_START),
                            (T_RVF_BUFFER **)(&p_msg_start));

      // If insufficient resources, then report a memory error and abort
      if(mb_status==RVF_YELLOW)
      {
        // deallocate the memory
        rvf_free_buf((T_RVF_BUFFER *)p_msg_start);
        audio_midi_error_trace(AUDIO_ENTITY_NO_MEMORY);
#ifndef _WINDOWS
        ffs_close(ffs_fd);
#endif
        return(AUDIO_ERROR);
      }
      else
      {
        if(mb_status==RVF_RED)
        {
          audio_midi_error_trace(AUDIO_ENTITY_NO_MEMORY);
#ifndef _WINDOWS
          ffs_close(ffs_fd);
#endif
          return (AUDIO_ERROR);
        }
      }

      // fill the message id
      p_msg_start->os_hdr.msg_id=AUDIO_MIDI_START_REQ;

      // fill the address source id
      p_msg_start->os_hdr.src_addr_id =rvf_get_taskid();
      p_msg_start->os_hdr.dest_addr_id=p_audio_gbl_var->addrId;

      // fill the message parameters
      p_msg_start->audio_ffs_fd=ffs_fd;

      if(p_return_path->callback_func==NULL)
      {
        p_msg_start->return_path.addr_id=p_return_path->addr_id;
        p_msg_start->return_path.callback_func=NULL;
      }
      else
        p_msg_start->return_path.callback_func=p_return_path->callback_func;

      // send the messsage to the audio entity
      rvf_send_msg(p_audio_gbl_var->addrId,p_msg_start);

      return(AUDIO_OK);
    #else // L1_MIDI==1
      AUDIO_SEND_TRACE("MIDI not compiled",RV_TRACE_LEVEL_DEBUG_LOW);
      return(AUDIO_ERROR);
    #endif // L1_MIDI==1
  } /*********************** End of audio_midi_start function ******************/


  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_midi_stop                                          */
  /*                                                                              */
  /*    Purpose:  This function is called to stop MIDI file playback              */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        Return path.                                                          */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  T_AUDIO_RET audio_midi_stop(void)
  {
    #if (L1_MIDI==1)
      // Declare local variables
      T_RVF_MB_STATUS   mb_status  =RVF_GREEN;
      T_AUDIO_MIDI_STOP *p_msg_stop=NULL;

      /************************ audio_midi_stop function begins ****************/

      if(p_audio_gbl_var==NULL)
      {
        audio_midi_error_trace(AUDIO_ENTITY_NOT_START);
        return(AUDIO_ERROR);
      }

      // allocate the memory for the message to send
      mb_status=rvf_get_buf(p_audio_gbl_var->mb_external,
                            sizeof(T_AUDIO_MIDI_STOP),
                            (T_RVF_BUFFER **)(&p_msg_stop));

      // If insufficient resources, then report a memory error and abort
      if(mb_status==RVF_YELLOW)
      {
        // deallocate the memory
        rvf_free_buf((T_RVF_BUFFER *)p_msg_stop);
        audio_midi_error_trace(AUDIO_ENTITY_NO_MEMORY);
        return(AUDIO_ERROR);
      }
      else
      {
        if(mb_status==RVF_RED)
        {
          audio_midi_error_trace(AUDIO_ENTITY_NO_MEMORY);
          return(AUDIO_ERROR);
        }
      }

      // fill the message id
      p_msg_stop->os_hdr.msg_id=AUDIO_MIDI_STOP_REQ;

      // fill the address source id
      p_msg_stop->os_hdr.src_addr_id =rvf_get_taskid();
      p_msg_stop->os_hdr.dest_addr_id=p_audio_gbl_var->addrId;

      // send the messsage to the audio entity
      rvf_send_msg(p_audio_gbl_var->addrId,p_msg_stop);

      return(AUDIO_OK);
    #else // L1_MIDI==1
      AUDIO_SEND_TRACE("MIDI not compiled",RV_TRACE_LEVEL_DEBUG_LOW);
      return(AUDIO_ERROR);
    #endif // L1_MIDI==1
  } /*********************** End of audio_midi_stop function *******************/

#if (L1_MIDI == 1)

  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_midi_message_switch	                              */
  /*                                                                              */
  /*    Purpose:  Manage the message supply                                       */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        start or stop message from midi features                              */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        index of the manager                                                  */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  UINT8 audio_midi_message_switch(T_RV_HDR *p_message)
  {
    switch(p_message->msg_id)
    {
      case AUDIO_MIDI_START_REQ:
      case AUDIO_MIDI_STOP_REQ:
        return(AUDIO_MIDI);
      break;

      // driver init => check session_id is MIDI
      case AUDIO_DRIVER_INIT_STATUS_MSG:
      {
        UINT8 session_id=((T_AUDIO_DRIVER_INIT_STATUS *)p_message)->session_id;

        // session_id is MIDI
        if((session_id==AUDIO_MIDI_SESSION_ID) && (p_audio_gbl_var->midi.state!=AUDIO_IDLE))
          return(AUDIO_MIDI);
        else
          return(AUDIO_MIDI_NONE);
      }
      break;

      case AUDIO_DRIVER_NOTIFICATION_MSG:
      {
        UWORD8 channel_id;
        channel_id=((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id;
        if((channel_id==p_audio_gbl_var->midi.channel_id) && (p_audio_gbl_var->midi.state>AUDIO_WAIT_CHANNEL_ID))
          return(AUDIO_MIDI);
        else
          return(AUDIO_MIDI_NONE);
      }
      break;

      case AUDIO_DRIVER_STATUS_MSG:
      {
        UWORD8 channel_id;
        channel_id=((T_AUDIO_DRIVER_STATUS *)p_message)->channel_id;
        if((channel_id==p_audio_gbl_var->midi.channel_id) && (p_audio_gbl_var->midi.state>AUDIO_WAIT_CHANNEL_ID))
          return(AUDIO_MIDI);
        else
          return(AUDIO_MIDI_NONE);
      }
      break;

      default:
        return(AUDIO_MIDI_NONE);
      break;
    } // switch
  }


  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_midi_send_status                                   */
  /*                                                                              */
  /*    Purpose:  This function sends the MIDI play status to the entity          */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        status,                                                               */
  /*        return path                                                           */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  void audio_midi_send_status(T_AUDIO_RET status, T_RV_RETURN *return_path)
  {
    T_AUDIO_MIDI_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_MIDI_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_midi_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_MIDI_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_midi_manager                                       */
  /*                                                                              */
  /*    Purpose:  This function is called to manage a MIDI play manager           */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        Message to the audio entity                                           */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  void audio_midi_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;

    // initialize the return path
    return_path.callback_func=NULL;
    return_path.addr_id=p_audio_gbl_var->addrId;

    /**************** audio_midi_manager function begins ***********************/
    switch(p_audio_gbl_var->midi.state)
    {
      case AUDIO_IDLE:
      {
        switch(p_message->msg_id)
        {
          case AUDIO_MIDI_START_REQ:
          {
            T_AUDIO_DRIVER_PARAMETER driver_parameter;
            p_audio_gbl_var->midi.stop_req_allowed=TRUE;

            // save the return path + ffs_fd
            p_audio_gbl_var->midi.return_path.callback_func=((T_AUDIO_MIDI_START *)p_message)->return_path.callback_func;
            p_audio_gbl_var->midi.return_path.addr_id=((T_AUDIO_MIDI_START *)p_message)->return_path.addr_id;
            p_audio_gbl_var->midi.ffs_fd=((T_AUDIO_MIDI_START *)p_message)->audio_ffs_fd;

            // driver parameters
            driver_parameter.nb_buffer   = AUDIO_MIDI_NB_BUFFER;
            driver_parameter.buffer_size = AUDIO_MIDI_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_midi_session(&driver_parameter,&return_path);

            p_audio_gbl_var->midi.state=AUDIO_WAIT_CHANNEL_ID;
          }
          break;
          case AUDIO_MIDI_STOP_REQ:
          {
            audio_midi_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;  // AUDIO_IDLE

      case AUDIO_WAIT_CHANNEL_ID:
      {
        switch(p_message->msg_id)
        {
          case AUDIO_DRIVER_INIT_STATUS_MSG:
          {
            UINT8 *play_buffer;
            INT16 size_read;

            // 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->midi.channel_id=((T_AUDIO_DRIVER_INIT_STATUS *)p_message)->channel_id;

              // initializations
              p_audio_gbl_var->midi.size = AUDIO_MIDI_SIZE << 1;
              p_audio_gbl_var->midi.stop_req_allowed=TRUE;

              // fill all buffers in advance
              while(audio_driver_get_play_buffer(p_audio_gbl_var->midi.channel_id,&play_buffer)==AUDIO_OK)
              {
                // write from FLASH to RAM buffer
                if(p_audio_gbl_var->midi.ffs_fd!=NULL)
                {
#ifndef _WINDOWS
                  size_read=ffs_read(p_audio_gbl_var->midi.ffs_fd,play_buffer,p_audio_gbl_var->midi.size);
#else
                  size_read=p_audio_gbl_var->midi.size;
#endif
                  if(size_read<EFFS_OK)
                  {
#ifndef _WINDOWS
                    if(ffs_close(p_audio_gbl_var->midi.ffs_fd)!=EFFS_OK)
                      audio_mem_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE);
#endif
                    AUDIO_SEND_TRACE("AUDIO MIDI: FFS PLAY READ failed",RV_TRACE_LEVEL_DEBUG_LOW);
                    audio_mem_send_status(AUDIO_ERROR,p_audio_gbl_var->midi.channel_id,AUDIO_START_STATUS,return_path);
                    return;
                  }
                }

                AUDIO_SEND_TRACE_PARAM("AUDIO MIDI: size read",size_read,RV_TRACE_LEVEL_DEBUG_LOW);

                audio_driver_play_buffer(p_audio_gbl_var->midi.channel_id,play_buffer);
              }

              // send message
              audio_driver_start_session(p_audio_gbl_var->midi.channel_id,return_path);

              // change state
              p_audio_gbl_var->midi.state=AUDIO_WAIT_STOP;
            }
            else
            {
              audio_midi_error_trace(AUDIO_ERROR_START_EVENT);
              audio_midi_send_status(AUDIO_ERROR, &p_audio_gbl_var->midi.return_path);
              // change state
              p_audio_gbl_var->midi.state=AUDIO_IDLE;
            }
          }
          break;
          case AUDIO_MIDI_STOP_REQ:
            // change state
            p_audio_gbl_var->midi.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_DRIVER_NOTIFICATION_MSG:
          {
            UINT8 *play_buffer;
            INT16 size_read;

            // try to get a buffer
            if(audio_driver_get_play_buffer(p_audio_gbl_var->midi.channel_id,&play_buffer)==AUDIO_OK)
            {
#ifndef _WINDOWS
              size_read=ffs_read(p_audio_gbl_var->midi.ffs_fd,play_buffer,p_audio_gbl_var->midi.size);
#else
              size_read=p_audio_gbl_var->midi.size;
#endif
              if(size_read<EFFS_OK)
              {
                AUDIO_SEND_TRACE("AUDIO MIDI: FFS PLAY READ FILED",RV_TRACE_LEVEL_DEBUG_LOW);
                size_read=0;  // will put END_MASK in whole buffer so stops play
              }
              audio_driver_play_buffer(p_audio_gbl_var->midi.channel_id,play_buffer);

              if(size_read>0)
                AUDIO_SEND_TRACE_PARAM("AUDIO MIDI: size read",size_read,RV_TRACE_LEVEL_DEBUG_LOW);
              else
                AUDIO_SEND_TRACE("AUDIO MIDI: buffer not used",RV_TRACE_LEVEL_DEBUG_LOW);
            } // if(audio_driver_get_play_buffer(channel_id,&p_buffer)==AUDIO_OK)
            else
              AUDIO_SEND_TRACE("AUDIO MIDI: no buffer available",RV_TRACE_LEVEL_DEBUG_LOW);
          }
          break;  // case AUDIO_DRIVER_NOTIFICATION_MSG

          case AUDIO_MIDI_STOP_REQ:
            if(p_audio_gbl_var->midi.stop_req_allowed==TRUE)
            {
              p_audio_gbl_var->midi.stop_req_allowed=FALSE;
              audio_driver_stop_session(p_audio_gbl_var->midi.channel_id);
            }
            else
              AUDIO_SEND_TRACE("AUDIO MIDI: second stop request received",RV_TRACE_LEVEL_WARNING);
          break;

          case AUDIO_DRIVER_STATUS_MSG:
            if(p_audio_gbl_var->midi.ffs_fd!=NULL)
            {
#ifndef _WINDOWS
              if(ffs_close(p_audio_gbl_var->midi.ffs_fd)!=EFFS_OK) audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE);
#endif
              AUDIO_SEND_TRACE("AUDIO MIDI: close FFS file", RV_TRACE_LEVEL_DEBUG_LOW);
            }
            audio_midi_send_status(AUDIO_OK,&p_audio_gbl_var->midi.return_path);
            p_audio_gbl_var->midi.state=AUDIO_IDLE;
          break;
        }
      }
      break; // WAIT_STOP

      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->midi.channel_id=((T_AUDIO_DRIVER_INIT_STATUS *)p_message)->channel_id;

              audio_driver_stop_session(p_audio_gbl_var->midi.channel_id);

              // change state
              p_audio_gbl_var->midi.state=AUDIO_WAIT_DRIVER_STOP_CON;
            }
            else
            {
              // close file
              if(p_audio_gbl_var->midi.ffs_fd!=NULL)
              {
#ifndef _WINDOWS
                if(ffs_close(p_audio_gbl_var->midi.ffs_fd)!=EFFS_OK) audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE);
#endif
                AUDIO_SEND_TRACE("AUDIO MIDI: close FFS file:",RV_TRACE_LEVEL_DEBUG_LOW);
              }

              audio_midi_send_status(AUDIO_OK,&p_audio_gbl_var->midi.return_path);

              // change state
              p_audio_gbl_var->midi.state=AUDIO_IDLE;
            }
          }
          break;
          case AUDIO_MIDI_STOP_REQ:
            audio_midi_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(p_audio_gbl_var->midi.ffs_fd!=NULL)
              {
#ifndef _WINDOWS
                if(ffs_close(p_audio_gbl_var->midi.ffs_fd)!=EFFS_OK) audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE);
#endif
                AUDIO_SEND_TRACE("AUDIO MIDI: close FFS file",RV_TRACE_LEVEL_DEBUG_LOW);
              }

              audio_midi_send_status(((T_AUDIO_DRIVER_STATUS *)p_message)->status,
                                     &p_audio_gbl_var->midi.return_path);
              p_audio_gbl_var->midi.state=AUDIO_IDLE;
            }
          }
          break;
          case AUDIO_MIDI_STOP_REQ:
            audio_midi_error_trace(AUDIO_ERROR_STOP_EVENT);
          break;
        }
      } //case AUDIO_WAIT_DRIVER_STOP_CON:
      break;
    }
  } /*********************** End of audio_midi_manager function **********************/

  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_driver_midi_manager                                */
  /*                                                                              */
  /*    Purpose:  This function is called to manage a MIDI manager                */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        Message to the audio entity                                           */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  T_AUDIO_RET audio_driver_midi_manager(T_RV_HDR *p_message, T_AUDIO_DRIVER_SESSION *p_session)
  {
    /**************** audio_driver_midi_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_MIDI_REQ));
        ((T_MMI_MIDI_REQ *)(p_session->session_req.p_l1_send_message))->session_id=AUDIO_MIDI_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 midi message to the L1
        audio_send_l1_message(MMI_MIDI_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_MIDI_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_MIDI_STOP_REQ,p_send_message);
          return(AUDIO_OK);
        }
        return(AUDIO_ERROR);
      }
      break;
    }
  } /*********************** End of audio_driver_midi_manager function **********************/


  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_driver_init_midi_session                           */
  /*                                                                              */
  /*    Purpose:  This function is called in order to initialize MIDI             */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        Specific MIDI parameters                                              */
  /*        Driver parameters                                                     */
  /*        Return path                                                           */
  /*                                                                              */
  /*    Output Parameters:                                                        */
  /*         Validation of the parameters                                         */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  T_AUDIO_RET audio_driver_init_midi_session(T_AUDIO_DRIVER_PARAMETER *p_driver_parameter, T_RV_RETURN *p_return_path)
  {
  #if (L1_MIDI==1)
    /* Declare local variables.                                                 */
    T_RVF_MB_STATUS   mb_status = RVF_GREEN;
    T_AUDIO_DRIVER_INIT_MIDI_SESSION *p_msg  = NULL;

    /************************ audio_keybeep_stop function begins ****************/

    if (p_audio_gbl_var == NULL )
    {
      audio_driver_error_trace(AUDIO_ENTITY_NOT_START);
      return(AUDIO_ERROR);
    }

    /* If bad parameters report an error and abort.*/
    if(p_driver_parameter->nb_buffer<2)
    {
      audio_driver_error_trace(AUDIO_ENTITY_BAD_PARAMETER);
      return (AUDIO_ERROR);
    }

    /* allocate the memory for the message to send */
    mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal,
                             sizeof (T_AUDIO_DRIVER_INIT_MIDI_SESSION),
                             (T_RVF_BUFFER **) (&p_msg));

    /* If insufficient resources, then report a memory error and abort.         */
    if (mb_status == RVF_YELLOW)
    {
      /* deallocate the memory */
      rvf_free_buf((T_RVF_BUFFER *)p_msg);
      audio_driver_error_trace(AUDIO_ENTITY_NO_MEMORY);
      return (AUDIO_ERROR);
    }
    else
    if (mb_status == RVF_RED)
    {
      audio_driver_error_trace(AUDIO_ENTITY_NO_MEMORY);
      return (AUDIO_ERROR);
    }

    /* fill the message id */
    p_msg->os_hdr.msg_id = AUDIO_DRIVER_INIT_MIDI_SESSION;
    p_msg->os_hdr.dest_addr_id = p_audio_gbl_var->addrId;

    /* fill parameters */
    p_msg->driver_parameter.buffer_size = p_driver_parameter->buffer_size;
    p_msg->driver_parameter.nb_buffer   = p_driver_parameter->nb_buffer;

    if (p_return_path->callback_func == NULL)
    {
      p_msg->return_path.addr_id = p_return_path->addr_id;
      p_msg->return_path.callback_func = NULL;
    }
    else
      p_msg->return_path.callback_func = p_return_path->callback_func;

    /* send the messsage to the audio entity */
    rvf_send_msg (p_audio_gbl_var->addrId, p_msg);

    return (AUDIO_OK);
    #else  // L1_MIDI==1
      AUDIO_SEND_TRACE("MIDI not compiled", RV_TRACE_LEVEL_DEBUG_LOW);
      return (AUDIO_ERROR);
    #endif // L1_MIDI==1
  }


  /********************************************************************************/
  /*                                                                              */
  /*    Function Name:   audio_midi_l1_simulator                                  */
  /*                                                                              */
  /*    Purpose:  This function simulates the L1 for MIDI                         */
  /*                                                                              */
  /*    Input Parameters:                                                         */
  /*        event: Event that triggered the function                              */
  /*        p_msg: Message (if any) associated with the event                     */
  /*                                                                              */
  /*    Note:                                                                     */
  /*        None.                                                                 */
  /*                                                                              */
  /*    Revision History:                                                         */
  /*        None.                                                                 */
  /*                                                                              */
  /********************************************************************************/
  void audio_midi_l1_simulator(UINT16 event, T_RV_HDR *p_message)
  {
#ifdef _WINDOWS
    enum { WAIT_START_REQ, WAIT_STOP };

    T_RVF_MB_STATUS mb_status;
    T_RV_RETURN *return_path=&(p_audio_gbl_var->audio_driver_session[p_audio_gbl_var->midi.channel_id].session_req.return_path);

    switch(p_audio_gbl_var->midi.l1_state)
    {
      case WAIT_START_REQ:
        if(p_message->msg_id==MMI_MIDI_START_REQ)
        {
          rvf_start_timer(AUDIO_MIDI_L1_SIMUL_TIMER,
                          RVF_MS_TO_TICKS(1000),
                          AUDIO_MIDI_L1_SIMUL_ONE_SHOT_TIMER);
          p_audio_gbl_var->midi.counter=10;

          // send MMI_MIDI_START_CON message to the Riviera audio entity
          mb_status=rvf_get_buf(p_audio_gbl_var->mb_internal,
                                sizeof(T_AUDIO_DRIVER_NOTIFICATION),
                                (T_RVF_BUFFER **)(&p_message));
          if(mb_status==RVF_RED)
          {
            AUDIO_SEND_TRACE("AUDIO entity has no memory for driver notification",RV_TRACE_LEVEL_ERROR);
            return;
          }
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->header.msg_id=MMI_MIDI_START_CON;
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id=p_audio_gbl_var->midi.channel_id;
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer=NULL;
          if(return_path->callback_func==NULL)
            rvf_send_msg(return_path->addr_id, p_message);
          else
          {
            (*return_path->callback_func)((void *)(p_message));
            rvf_free_buf((T_RVF_BUFFER *)p_message);
          }

          p_audio_gbl_var->midi.l1_state=WAIT_STOP;
          return;
        }
      break;

      case WAIT_STOP:
        if(event & AUDIO_MIDI_L1_SIMUL_TIMER_EVT_MASK)
        {
          p_audio_gbl_var->midi.counter--;

          // switch buffer
          {
            T_AUDIO_DRIVER_SESSION *p=&p_audio_gbl_var->audio_driver_session[p_audio_gbl_var->midi.channel_id];
            p->session_info.index_l1++;
            if(p->session_info.index_l1==p->session_req.nb_buffer) p->session_info.index_l1=0;
          }

          // send notification message to the Riviera audio entity
          mb_status=rvf_get_buf(p_audio_gbl_var->mb_internal,
                                sizeof(T_AUDIO_DRIVER_NOTIFICATION),
                                (T_RVF_BUFFER **)(&p_message));
          if(mb_status==RVF_RED)
          {
            AUDIO_SEND_TRACE("AUDIO entity has no memory for driver notification",RV_TRACE_LEVEL_ERROR);
            return;
          }
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->header.msg_id=AUDIO_DRIVER_NOTIFICATION_MSG;
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id=p_audio_gbl_var->midi.channel_id;
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer=NULL;
          if(return_path->callback_func==NULL)
            rvf_send_msg(return_path->addr_id, p_message);
          else
          {
            (*return_path->callback_func)((void *)(p_message));
            rvf_free_buf((T_RVF_BUFFER *)p_message);
          }

          // check if we're done with the simulation
          if(p_audio_gbl_var->midi.counter==0)
          {
            rvf_stop_timer(AUDIO_MIDI_L1_SIMUL_TIMER);

            // send MMI_MIDI_STOP_CON message to the Riviera audio entity
            mb_status=rvf_get_buf(p_audio_gbl_var->mb_internal,
                                  sizeof(T_AUDIO_DRIVER_NOTIFICATION),
                                  (T_RVF_BUFFER **)(&p_message));
            if(mb_status==RVF_RED)
            {
              AUDIO_SEND_TRACE("AUDIO entity has no memory for driver notification",RV_TRACE_LEVEL_ERROR);
              return;
            }
            ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->header.msg_id=MMI_MIDI_STOP_CON;
            ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id=p_audio_gbl_var->midi.channel_id;
            ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer=NULL;
            if(return_path->callback_func==NULL)
              rvf_send_msg(return_path->addr_id, p_message);
            else
            {
              (*return_path->callback_func)((void *)(p_message));
              rvf_free_buf((T_RVF_BUFFER *)p_message);
            }

            p_audio_gbl_var->midi.l1_state=WAIT_START_REQ;
            return;
          }
          rvf_start_timer(AUDIO_MIDI_L1_SIMUL_TIMER,
                          RVF_MS_TO_TICKS(1000),
                          AUDIO_MIDI_L1_SIMUL_ONE_SHOT_TIMER);
        }
        if(p_message->msg_id==MMI_MIDI_STOP_REQ)
        {
          rvf_stop_timer(AUDIO_MIDI_L1_SIMUL_TIMER);

          // send MMI_MIDI_STOP_CON message to the Riviera audio entity
          mb_status=rvf_get_buf(p_audio_gbl_var->mb_internal,
                                sizeof(T_AUDIO_DRIVER_NOTIFICATION),
                                (T_RVF_BUFFER **)(&p_message));
          if(mb_status==RVF_RED)
          {
            AUDIO_SEND_TRACE("AUDIO entity has no memory for driver notification",RV_TRACE_LEVEL_ERROR);
            return;
          }
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->header.msg_id=MMI_MIDI_STOP_CON;
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id=p_audio_gbl_var->midi.channel_id;
          ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer=NULL;
          if(return_path->callback_func==NULL)
            rvf_send_msg(return_path->addr_id, p_message);
          else
          {
            (*return_path->callback_func)((void *)(p_message));
            rvf_free_buf((T_RVF_BUFFER *)p_message);
          }

          p_audio_gbl_var->midi.l1_state=WAIT_START_REQ;
          return;
        }
      break;
    }
#endif // _WINDOWS
  }

#endif // #if (L1_MIDI == 1)
#endif // #ifdef RVM_AUDIO_MAIN_SWE