/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2008/X/X - 2016/12/01
/// 
/// @brief  DirectX サウンド周り。
/// 
/// ****************************************************************************
#pragma once


#include "CPL_DX_Sound.h"

#include "CPL_DX_SoundBufferStatic.cpp"
#include "CPL_DX_SoundBufferStream.cpp"

namespace CPL {
namespace DX {
namespace Audio {

// _____________________________________________________________________________
/// @copydoc SoundPlayerEntity_for_Decompressed::Create(_in<CpDXSound>,_in<sdptr<Core::BaseSoundManager>>,_in<DWORD>)
/// @param[in] in_flag_decompressed
///   : true  : データを全て解凍し、メモリ上に展開する。\n
///   : false : ストリームから順次読み込む。
/// 
/// @retval true  : 作成成功。
/// @retval false : 作成失敗。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  SoundPlayer::Create
    ( _in<CpDXSound>                     in_cp_dx_sound
    , _in<sdptr<Core::BaseSoundManager>> in_sp_sound_stream
    , _in<bool >                         in_flag_decompressed
    , _in<DWORD>                         in_flags )
{
  using SPD = SoundPlayerEntity_for_Decompressed;
  using SPS = SoundPlayerEntity_for_Stream;

  try {
    if( in_flag_decompressed )
    {
      setEntity
        ( CPL_MAKE_SHARED( SPD, in_cp_dx_sound, in_sp_sound_stream, in_flags ) );
    }
    else
    {
      setEntity
        ( CPL_MAKE_SHARED( SPS, in_cp_dx_sound, in_sp_sound_stream, in_flags ) );
    }
    return true;
  }
  catch(...)
  {
    return false;
  }
}


// _____________________________________________________________________________
/// @copydoc SoundPlayerEntity_for_Decompressed::Create(_in<CpDXSound>,pin<str_type>,_in<Core::StringA>,_in<DWORD>)
/// @param[in] in_flag_decompressed
///   : true  - データを全て解凍し、メモリ上に展開する。\n
///   : false - ストリームから順次読み込む。            \n
///   : 　　　　ただし、２秒以下のサウンドは全てメモリ上に展開する。
/// 
/// @retval true  : 作成成功。
/// @retval false : 作成失敗。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  SoundPlayer::Create
    ( _in<CpDXSound    > in_cp_dx_sound
    , pin<str_type     > in_path
    , _in<Core::StringA> in_mask
    , _in<bool         > in_flag_decompressed
    , _in<DWORD        > in_flags
    )
{
  using SPD = SoundPlayerEntity_for_Decompressed;
  using SPS = SoundPlayerEntity_for_Stream;

  try {
    if( in_flag_decompressed )
    {
      setEntity
        ( CPL_MAKE_SHARED( SPD, in_cp_dx_sound, in_path, in_mask, in_flags ) );
    }
    else
    {
      setEntity
        ( CPL_MAKE_SHARED( SPS, in_cp_dx_sound, in_path, in_mask, in_flags ) );
    }
    return true;
  }
  catch(...)
  {
    return false;
  }
}



// _____________________________________________________________________________
/// @brief デフォルトコンストラクタ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SoundPlayer::SoundPlayer()
{}

// _____________________________________________________________________________
/// @brief コンストラクタ（サウンドストリーム指定バージョン）
/// @copydetails SoundPlayer::Create(_in<CpDXSound>,_in<sdptr<Core::BaseSoundManager>>,_in<bool>,_in<DWORD>)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SoundPlayer::SoundPlayer
( _in<CpDXSound                    > in_cp_dx_sound
, _in<sdptr<Core::BaseSoundManager>> in_sp_sound_stream
, _in<bool                         > in_flag_decompressed
, _in<DWORD                        > in_flags )
{
  Create( in_cp_dx_sound, in_sp_sound_stream, in_flag_decompressed, in_flags );
}


// _____________________________________________________________________________
/// @brief コンストラクタ（ファイルパス指定バージョン）
/// @copydetails SoundPlayer::Create(_in<CpDXSound>,pin<str_type>,_in<Core::StringA>,_in<bool>,_in<DWORD>)
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SoundPlayer::SoundPlayer
( _in<CpDXSound    > in_cp_dx_sound
, pin<str_type     > in_path
, _in<Core::StringA> in_mask
, _in<bool         > in_flag_decompressed
, _in<DWORD        > in_flags )
{
  Create( in_cp_dx_sound, in_path, in_mask, in_flag_decompressed, in_flags );
}






// _____________________________________________________________________________
/// @brief 初期化
/// 
/// ※ 最初に一度だけ呼び出す。
/// 
/// @param[in] in_hdl_window
///   : ウィンドウハンドルを指定します。\n
///   : 協調レベルの設定に使用されます。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int Sound::Init( _in<HWND> in_hdl_window )
{
  static int f_init = false;
  HRESULT hr = 0;

  if( m_cp_sound == nullptr )
  {
    // DirectSoundの作成
    hr = DirectSoundCreate8( nullptr, &m_cp_sound, nullptr );
    if( FAILED(hr) )
    {
      return false;
    }
    // 初期化
    m_cp_sound->Initialize( nullptr );
  }

  // DirectSoundの強調レベルの設定
  hr = m_cp_sound->SetCooperativeLevel( in_hdl_window, DSSCL_PRIORITY );
  if( FAILED(hr) )
  {
    // 普通レベルでトライ
    hr = m_cp_sound->SetCooperativeLevel( in_hdl_window, DSSCL_NORMAL );
    if( FAILED(hr) )
    {
      return false;
    }
  }

  // プライマリ・サウンドバッファの作成
  DSBUFFERDESC desc;
  ::memset( &desc, 0, sizeof(desc) );
  desc.dwSize  = sizeof(desc);
  desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_PRIMARYBUFFER;
  hr = m_cp_sound->CreateSoundBuffer( &desc, &m_cp_prim_buf, nullptr );
  if( FAILED(hr) )
  {
    return false;
  }

  f_init = true;

  return f_init;
}


} // namespace Audio
} // namespace DX
} // namespace CPL
