//******************************************************************************
//
// Simple MIDI Library / SMOutDevCtrlEx
//
// 拡張MIDI出力デバイス制御クラス
//
// Copyright (C) 2010-2021 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

#import "YNBaseLib.h"
#import "SMOutDevCtrlEx.h"


//******************************************************************************
// コンストラクタ
//******************************************************************************
SMOutDevCtrlEx::SMOutDevCtrlEx()
{
	unsigned char portNo = 0;
	
	for (portNo = 0; portNo < SM_MIDIOUT_PORT_NUM_MAX; portNo++) {
		m_PortType[portNo] = PortNone;
	}
}

//******************************************************************************
// デストラクタ
//******************************************************************************
SMOutDevCtrlEx::~SMOutDevCtrlEx()
{
}

//******************************************************************************
// 内部シンセサイザ：Wavetableファイルパス登録
//******************************************************************************
int SMOutDevCtrlEx::SetInternalSynthsizerWavetableFilePath(
		NSString* pWavetableFilePath
	)
{
	int result = 0;
	
	result = m_WavetableSynthCtrl.SetWavetableFilePath(pWavetableFilePath);
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// 初期化
//******************************************************************************
int SMOutDevCtrlEx::Initialize()
{
	int result = 0;
	
	result = ClearPortInfo();
	if (result != 0) goto EXIT;
	
	result = m_WavetableSynthCtrl.Initialize();
	if (result != 0) goto EXIT;
	
	result = m_OutDevCtrl.Initialize();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// デバイス数取得
//******************************************************************************
unsigned int SMOutDevCtrlEx::GetDevNum()
{
	unsigned int devNum = 0;
	
	//Wavetableシンセサイザをカウントする
	devNum = 1;
	
	//CoreMIDI出力デバイス数を加算する
	devNum += m_OutDevCtrl.GetDevNum();
	
	return devNum;
}

//******************************************************************************
// デバイス表示名称取得
//******************************************************************************
NSString* SMOutDevCtrlEx::GetDevDisplayName(
		unsigned int index
	)
{
	NSString* pDisplayName = nil;
	
	if (index == 0) {
		pDisplayName = m_WavetableSynthCtrl.GetDevDisplayName();
	}
	else {
		pDisplayName = m_OutDevCtrl.GetDevDisplayName(index - 1);
	}
	
	return pDisplayName;
}

//******************************************************************************
// デバイス識別名取得
//******************************************************************************
NSString* SMOutDevCtrlEx::GetDevIdName(
		unsigned int index
	)
{
	NSString* pDevIdName = nil;
	
	if (index == 0) {
		pDevIdName = m_WavetableSynthCtrl.GetDevIdName();
	}
	else {
		pDevIdName = m_OutDevCtrl.GetDevIdName(index - 1);
	}
	
	return pDevIdName;
}

//******************************************************************************
// メーカー名取得
//******************************************************************************
NSString* SMOutDevCtrlEx::GetManufacturerName(
		unsigned int index
	)
{
	NSString* pManufacturerName = nil;
	
	if (index == 0) {
		pManufacturerName = m_WavetableSynthCtrl.GetManufacturerName();
	}
	else {
		pManufacturerName = m_OutDevCtrl.GetManufacturerName(index - 1);
	}
	
	return pManufacturerName;
}

//******************************************************************************
// ポート対応デバイス登録
//******************************************************************************
int SMOutDevCtrlEx::SetDevForPort(
		unsigned char portNo,
		NSString* pIdName,
		NSString* pDisplayName
	)
{
	int result = 0;
	
	if (portNo >= SM_MIDIOUT_PORT_NUM_MAX) {
		result = YN_SET_ERR(@"Program error.", portNo, 0);
		goto EXIT;
	}
	
	if ([pIdName isEqualToString:m_WavetableSynthCtrl.GetDevIdName()]) {
		m_PortType[portNo] = PortWavetableSynth;
	}
	else {
		m_PortType[portNo] = PortCoreMIDIDevice;
		result = m_OutDevCtrl.SetDevForPort(portNo, pIdName, pDisplayName);
		if (result != 0) goto EXIT;
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// 全デバイスのオープン
//******************************************************************************
int SMOutDevCtrlEx::OpenPortDevAll()
{
	int result = 0;
	unsigned char portNo = 0;
	bool isActiveWavetableSynth = false;
	
	//Wavetable読み込みで負荷が発生するため選択されているときだけオープン
	for (portNo = 0; portNo < SM_MIDIOUT_PORT_NUM_MAX; portNo++) {
		if (m_PortType[portNo] == PortWavetableSynth) {
			isActiveWavetableSynth = true;
		}
	}
	
	//バックグラウド演奏対応
	//  オーディオユニットが存在しない状態でバックグラウンドに遷移するとサスペンドされてしまう
	//  デバイスの選択状態状態に関係なく常にWavetableシンセサイザをオープンする
	isActiveWavetableSynth = true;
	
	//Wabetableシンセサイザのオープン
	if (isActiveWavetableSynth) {
		result = m_WavetableSynthCtrl.Open();
		if (result != 0) goto EXIT;
	}
	
	//CoreMIDIデバイスのオープン
	result = m_OutDevCtrl.OpenPortDevAll();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// 全デバイスのクローズ
//******************************************************************************
int SMOutDevCtrlEx::ClosePortDevAll()
{
	int result = 0;
	
	result = m_WavetableSynthCtrl.Close();
	if (result != 0) goto EXIT;
	
	result = m_OutDevCtrl.ClosePortDevAll();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// ポート情報クリア
//******************************************************************************
int SMOutDevCtrlEx::ClearPortInfo()
{
	int result = 0;
	unsigned char portNo = 0;
	
	result = m_OutDevCtrl.ClearPortInfo();
	if (result != 0) goto EXIT;
	
	for (portNo = 0; portNo < SM_MIDIOUT_PORT_NUM_MAX; portNo++) {
		m_PortType[portNo] = PortNone;
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// MIDIデータ送信（ショートメッセージ）
//******************************************************************************
int SMOutDevCtrlEx::SendShortMsg(
		unsigned char portNo,
		unsigned char* pMsg,
		unsigned int size
	)
{
	int result = 0;
	
	if (portNo >= SM_MIDIOUT_PORT_NUM_MAX) {
		result = YN_SET_ERR(@"Program error.", portNo, 0);
		goto EXIT;
	}
	
	if (m_PortType[portNo] == PortWavetableSynth) {
		result = m_WavetableSynthCtrl.SendShortMsg(pMsg, size);
		if (result != 0) goto EXIT;
	}
	else if (m_PortType[portNo] == PortCoreMIDIDevice) {
		result = m_OutDevCtrl.SendShortMsg(portNo, pMsg, size);
		if (result != 0) goto EXIT;
	}
	else {
		//出力先が指定されていないポートに対するデータ送信のため無視する
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// MIDIデータ送信（ロングメッセージ）
//******************************************************************************
int SMOutDevCtrlEx::SendLongMsg(
		unsigned char portNo,
		unsigned char* pMsg,
		unsigned int size
	)
{
	int result = 0;
	
	if (portNo >= SM_MIDIOUT_PORT_NUM_MAX) {
		result = YN_SET_ERR(@"Program error.", portNo, 0);
		goto EXIT;
	}
	
	if (m_PortType[portNo] == PortWavetableSynth) {
		result = m_WavetableSynthCtrl.SendLongMsg(pMsg, size);
		if (result != 0) goto EXIT;
	}
	else if (m_PortType[portNo] == PortCoreMIDIDevice) {
		result = m_OutDevCtrl.SendLongMsg(portNo, pMsg, size);
		if (result != 0) goto EXIT;
	}
	else {
		//出力先が指定されていないポートに対するデータ送信のため無視する
	}
	
EXIT:;
	return result;
}

//******************************************************************************
// 全ポートノートオフ
//******************************************************************************
int SMOutDevCtrlEx::NoteOffAll()
{
	int result = 0;
	
	result = m_WavetableSynthCtrl.NoteOffAll();
	if (result != 0) goto EXIT;
	
	result = m_OutDevCtrl.NoteOffAll();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// 全ポートサウンドオフ
//******************************************************************************
int SMOutDevCtrlEx::SoundOffAll()
{
	int result = 0;
	
	result = m_WavetableSynthCtrl.SoundOffAll();
	if (result != 0) goto EXIT;
	
	result = m_OutDevCtrl.SoundOffAll();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

//******************************************************************************
// オーディオセッションアクティブ設定
//******************************************************************************
int SMOutDevCtrlEx::SetAudioSessionActive(BOOL isActive)
{
	int result = 0;
	
	result = m_WavetableSynthCtrl.SetAudioSessionActive(isActive);
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

