//******************************************************************************
//
// 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_AppleDLSDevCtrl.Initialize();
	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;
	
	//Apple DLSデバイスをカウントする
	//Wavetableシンセサイザをカウントする
	devNum = 2;
	
	//CoreMIDI出力デバイス数を加算する
	devNum += m_OutDevCtrl.GetDevNum();
	
	return devNum;
}

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

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

//******************************************************************************
// メーカー名取得
//******************************************************************************
NSString* SMOutDevCtrlEx::GetManufacturerName(
		unsigned int index
	)
{
	NSString* pManufacturerName = nil;
	
	if (index == 0) {
		pManufacturerName = @"";
	}
	else if (index == 1) {
		pManufacturerName = m_WavetableSynthCtrl.GetManufacturerName();
	}
	else {
		pManufacturerName = m_OutDevCtrl.GetManufacturerName(index - 2);
	}
	
	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:SM_APPLE_DLS_DEVID_NAME]) {
		m_PortType[portNo] = PortAppleDLSDevice;
	}
	else 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;
	
	//Apple DLS デバイス
	result = m_AppleDLSDevCtrl.Open();
	if (result != 0) goto EXIT;
	
	//Wavetableシンセサイザ
	//Wavetable読み込みで負荷が発生するため選択されているときだけオープン
	for (portNo = 0; portNo < SM_MIDIOUT_PORT_NUM_MAX; portNo++) {
		if (m_PortType[portNo] == PortWavetableSynth) {
			isActiveWavetableSynth = true;
		}
	}
	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_AppleDLSDevCtrl.Close();
	if (result != 0) goto EXIT;
	
	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] == PortAppleDLSDevice) {
		result = m_AppleDLSDevCtrl.SendShortMsg(pMsg, size);
		if (result != 0) goto EXIT;
	}
	else 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] == PortAppleDLSDevice) {
		result = m_AppleDLSDevCtrl.SendLongMsg(pMsg, size);
		if (result != 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_AppleDLSDevCtrl.NoteOffAll();
	if (result != 0) goto EXIT;
	
	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_AppleDLSDevCtrl.SoundOffAll();
	if (result != 0) goto EXIT;
	
	result = m_WavetableSynthCtrl.SoundOffAll();
	if (result != 0) goto EXIT;
	
	result = m_OutDevCtrl.SoundOffAll();
	if (result != 0) goto EXIT;
	
EXIT:;
	return result;
}

