diff src/cs/services/audio/audio_midi.c @ 0:92470e5d0b9e

src: partial import from FC Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 15 May 2020 01:28:16 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/audio/audio_midi.c	Fri May 15 01:28:16 2020 +0000
@@ -0,0 +1,961 @@
+/****************************************************************************/
+/*                                                                          */
+/*  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