text: /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license that can
   *  be found in the License.html file in the root of the source tree.
   */
  
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  //
  // Information about OpenMG (OMA) files
  //
  //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  //---------------------------------------------------------------------------
  // Pre-compilation
  #include "MediaInfo/PreComp.h"
  #ifdef __BORLANDC__
      #pragma hdrstop
  #endif
  //---------------------------------------------------------------------------
  
  //---------------------------------------------------------------------------
  #include "MediaInfo/Setup.h"
  //---------------------------------------------------------------------------
  
  //---------------------------------------------------------------------------
  #if defined(MEDIAINFO_OPENMG_YES)
  //---------------------------------------------------------------------------
  
  //---------------------------------------------------------------------------
  #include "MediaInfo/Audio/File_OpenMG.h"
  //---------------------------------------------------------------------------
  
  namespace MediaInfoLib
  {
  
  //***************************************************************************
  // Info
  //***************************************************************************
  
  //---------------------------------------------------------------------------
  static const char* OpenMG_CodecID_Format (int8u CodecID)
  {
      switch (CodecID)
      {
          case  0 :
          case  1 :
                      return "Atrac3";
          case  3 :   return "MPEG Audio";
          case  4 :   return "PCM";
          case  5 :   return "WMA";
          default :   return "";
      }
  }
  
  //---------------------------------------------------------------------------
  static const char* OpenMG_CodecID_Encryption (int8u CodecID)
  {
      switch (CodecID)
      {
          case  1 :   return "SDMI";
          default :   return "";
      }
  }
  
  //---------------------------------------------------------------------------
  static int32u OpenMG_SamplingRate (int8u SamplingRate_Code)
  {
      switch (SamplingRate_Code)
      {
          case   0 : return 32000;
          case   1 : return 44100;
          case   2 : return 44800;
          case   3 : return 88200;
          case   4 : return 96000;
          default  : return 0;
      }
  }
  
  //---------------------------------------------------------------------------
  static int8u OpenMG_Channels (int8u Channels_Code)
  {
      if (Channels_Code<=4)
          return Channels_Code;
      else
          return Channels_Code+1; //+LFE
  }
  
  //---------------------------------------------------------------------------
  static const char* OpenMG_ChannelPositions (int8u Channels_Code)
  {
      switch (Channels_Code)
      {
          case  1 :   return "Front: C";
          case  2 :   return "Front: L R";
          case  3 :   return "Front: L R, Side: C";
          case  4 :   return "Front: L R, Back: L R";
          case  5 :   return "Front: L C R, Side: L R, LFE";
          case  6 :   return "Front: L C R, Side: L R, Back: C, LFE";
          case  7 :   return "Front: L C R, Side: L R, Back: L R, LFE";
          default :   return "";
      }
  }
  
  //---------------------------------------------------------------------------
  static const char* OpenMG_ChannelLayout (int8u Channels_Code)
  {
      switch (Channels_Code)
      {
          case  1 :   return "C";
          case  2 :   return "L R";
          case  3 :   return "L R S";
          case  4 :   return "L R BL BR";
          case  5 :   return "L R C SL SR LFE";
          case  6 :   return "L R C SL SR BC LFE";
          case  7 :   return "L R C SL SR BL BR LFE";
          default :   return "";
      }
  }
  
  //***************************************************************************
  // Constructor/Destructor
  //***************************************************************************
  
  //---------------------------------------------------------------------------
  File_OpenMG::File_OpenMG()
  {
      //File__Tags_Helper
      Base=this;
  
      //Config
      #if MEDIAINFO_TRACE
          Trace_Layers_Update(8); //Stream
      #endif //MEDIAINFO_TRACE
      StreamSource=IsStream;
  }
  
  //***************************************************************************
  // Streams management
  //***************************************************************************
  
  //---------------------------------------------------------------------------
  void File_OpenMG::Streams_Fill()
  {
      Fill(Stream_General, 0, General_Format, "OpenMG");
  
      File__Tags_Helper::Stream_Prepare(Stream_Audio);
  
      File__Tags_Helper::Streams_Fill();
  }
  
  //***************************************************************************
  // Buffer - File header
  //***************************************************************************
  
  //---------------------------------------------------------------------------
  bool File_OpenMG::FileHeader_Begin()
  {
      if (!File__Tags_Helper::FileHeader_Begin())
          return false;
  
      //Synchro
      if (Buffer_Offset+3>Buffer_Size)
          return false;
  
      // Testing
      if (Buffer[Buffer_Offset  ]!=0x45 // "EA3"
       || Buffer[Buffer_Offset+1]!=0x41
       || Buffer[Buffer_Offset+2]!=0x33)
      {
          File__Tags_Helper::Reject();
          return false;
      }
  
      return true;
  }
  
  //---------------------------------------------------------------------------
  void File_OpenMG::FileHeader_Parse()
  {
      //Parsing
      int16u Size, FrameSize=0;
      int8u  Flags, CodecID, SamplingRate_Code=0, Channels_Code=0;
      bool  JointStereo=false;
      Skip_C3(                                                    "Code");
      Get_B1 (Flags,                                              "Flags");
      Get_B2 (Size,                                               "Size");
      Skip_XX(26,                                                 "Unknown");
      Get_B1 (CodecID,                                            "Coded ID"); Param_Info1(OpenMG_CodecID_Format(CodecID));
      if (CodecID<=1) //Atrac3
      {
          BS_Begin();
          Skip_S1(7,                                              "Unknown");
          Get_SB (   JointStereo,                                 "Joint Stereo");
          Get_S1 (3, SamplingRate_Code,                           "Sampling Rate"); Param_Info2(OpenMG_SamplingRate(SamplingRate_Code), " Hz");
          Get_S1 (3, Channels_Code,                               "Channels"); Param_Info2(OpenMG_Channels(Channels_Code), " channel(s)");
          Get_S2 (10, FrameSize,                                  "Frame size");
          BS_End();
      }
      Skip_XX(Size-Element_Offset,                                "Unknown");
  
      FILLING_BEGIN();
          if (!Status[IsAccepted])
          {
              File__Tags_Helper::Accept();
  
              Fill(Stream_Audio, 0, Audio_Format, OpenMG_CodecID_Format(CodecID));
              Fill(Stream_Audio, 0, Audio_Encryption, OpenMG_CodecID_Encryption(CodecID));
              int64u StreamSize=(int64u)-1;
              if (File_Size!=(int64u)-1)
              {
                  StreamSize=File_Size-(Buffer_Offset+Element_Size);
                  Fill(Stream_Audio, 0, Audio_StreamSize, StreamSize);
              }
              if (CodecID<=1) // Atrac3
              {
                  Fill(Stream_Audio, 0, Audio_Channel_s_, OpenMG_Channels(Channels_Code));
                  Fill(Stream_Audio, 0, Audio_ChannelPositions, OpenMG_ChannelPositions(Channels_Code));
                  Fill(Stream_Audio, 0, Audio_ChannelLayout, OpenMG_ChannelLayout(Channels_Code));
                  if (Channels_Code==1 && JointStereo)
                      Fill(Stream_Audio, 0, Audio_Format_Settings_Mode, "Joint Stereo");
                  Fill(Stream_Audio, 0, Audio_SamplingRate, OpenMG_SamplingRate(SamplingRate_Code));
  
                  if (CodecID==1) //Protected
                      FrameSize++; //Not sure
                  FrameSize<<=3; //8-byte  blocks
                  int64u BitRate=OpenMG_SamplingRate(SamplingRate_Code)*FrameSize/256;
                  Fill(Stream_Audio, 0, Audio_BitRate, BitRate);
                  if (StreamSize!=(int64u)-1 && BitRate)
                      Fill(Stream_Audio, 0, Audio_Duration, StreamSize*8*1000/BitRate);
              }
          }
      FILLING_END();
  }
  
  //***************************************************************************
  // Buffer - Global
  //***************************************************************************
  
  //---------------------------------------------------------------------------
  void File_OpenMG::Read_Buffer_Continue()
  {
      //Parsing
      Skip_XX(File_Size-Buffer_Offset,                            "Data");
  
      File__Analyze::Finish();
  }
  
  } //NameSpace
  
  #endif
  