gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

deviceConnection.cpp (6090B)


      1 #include "deviceConnection.h"
      2 
      3 #include "remoteDevice.h"
      4 #include "dsp56kEmu/logging.h"
      5 #include "networkLib/logging.h"
      6 
      7 namespace bridgeClient
      8 {
      9 	static constexpr uint32_t g_replyTimeoutSecs = 10;
     10 
     11 	DeviceConnection::DeviceConnection(RemoteDevice& _device, std::unique_ptr<networkLib::TcpStream>&& _stream) : TcpConnection(std::move(_stream)), m_device(_device)
     12 	{
     13 		m_handleReplyFunc = [](bridgeLib::Command, baseLib::BinaryStream&){};
     14 
     15 		// send plugin description and device creation parameters, this will cause the server to either boot the device or ask for the rom if it doesn't have it yet
     16 		send(bridgeLib::Command::PluginInfo, m_device.getPluginDesc());
     17 
     18 		// do not send rom data now but only if the server asks for it
     19 		sendDeviceCreateParams(false);
     20 	}
     21 
     22 	DeviceConnection::~DeviceConnection()
     23 	{
     24 		shutdown();
     25 	}
     26 
     27 	void DeviceConnection::handleCommand(const bridgeLib::Command _command, baseLib::BinaryStream& _in)
     28 	{
     29 		switch (_command)
     30 		{
     31 		case bridgeLib::Command::RequestRom:
     32 			sendDeviceCreateParams(true);
     33 			break;
     34 		default:
     35 			TcpConnection::handleCommand(_command, _in);
     36 			break;
     37 		}
     38 	}
     39 
     40 	void DeviceConnection::handleData(const bridgeLib::DeviceDesc& _desc)
     41 	{
     42 		m_deviceDesc = _desc;
     43 		m_device.onBootFinished(_desc);
     44 	}
     45 
     46 	void DeviceConnection::handleDeviceInfo(baseLib::BinaryStream& _in)
     47 	{
     48 		TcpConnection::handleDeviceInfo(_in);
     49 		m_handleReplyFunc(bridgeLib::Command::DeviceInfo, _in);
     50 	}
     51 
     52 	void DeviceConnection::handleException(const networkLib::NetException& _e)
     53 	{
     54 		m_device.onDisconnect();
     55 	}
     56 
     57 	void DeviceConnection::sendDeviceCreateParams(const bool _sendRom)
     58 	{
     59 		bridgeLib::DeviceCreateParams p;
     60 		p.params = m_device.getDeviceCreateParams();
     61 		if(!_sendRom)
     62 			p.params.romData.clear();	
     63 		send(bridgeLib::Command::DeviceCreateParams, p);
     64 	}
     65 
     66 	bool DeviceConnection::processAudio(const synthLib::TAudioInputs& _inputs, const synthLib::TAudioOutputs& _outputs, const uint32_t _size, const uint32_t _latency)
     67 	{
     68 		m_audioBuffers.writeInput(_inputs, _size);
     69 
     70 		std::unique_lock lock(m_cvWaitMutex);
     71 
     72 		const auto haveEnoughOutput = m_audioBuffers.getOutputSize() >= _size;
     73 
     74 		m_audioBuffers.setLatency(_latency, haveEnoughOutput ? 0 : _size);
     75 
     76 		const auto sendSize = m_audioBuffers.getInputSize();
     77 
     78 		if(haveEnoughOutput)
     79 		{
     80 			lock.unlock();
     81 
     82 			if(sendSize > 0)
     83 				sendAudio(m_audioBuffers, m_device.getChannelCountIn(), sendSize);
     84 			m_audioBuffers.readOutput(_outputs, _size);
     85 		}
     86 		else
     87 		{
     88 			assert(sendSize > 0);
     89 			sendAudio(m_audioBuffers, m_device.getChannelCountIn(), sendSize);
     90 
     91 			m_cvWait.wait_for(lock, std::chrono::seconds(g_replyTimeoutSecs), [this, _size]
     92 			{
     93 				return m_audioBuffers.getOutputSize() >= _size;
     94 			});
     95 
     96 			if(m_audioBuffers.getOutputSize() < _size)
     97 			{
     98 				LOG("Receive timeout, closing connection");
     99 				close();
    100 				return false;
    101 			}
    102 
    103 			m_audioBuffers.readOutput(_outputs, _size);
    104 		}
    105 		return true;
    106 	}
    107 
    108 	void DeviceConnection::handleAudio(baseLib::BinaryStream& _in)
    109 	{
    110 		{
    111 			std::unique_lock lock(m_cvWaitMutex);
    112 			TcpConnection::handleAudio(m_audioBuffers, _in);
    113 		}
    114 
    115 		m_cvWait.notify_one();
    116 	}
    117 
    118 	void DeviceConnection::handleMidi(const synthLib::SMidiEvent& _e)
    119 	{
    120 		m_midiOut.push_back(_e);
    121 	}
    122 
    123 	void DeviceConnection::readMidiOut(std::vector<synthLib::SMidiEvent>& _midiOut)
    124 	{
    125 		_midiOut.insert(_midiOut.end(), m_midiOut.begin(), m_midiOut.end());
    126 		m_midiOut.clear();
    127 	}
    128 
    129 	bool DeviceConnection::getDeviceState(std::vector<uint8_t>& _state, synthLib::StateType _type)
    130 	{
    131 		return sendAwaitReply([this, _type]
    132 		{
    133 			bridgeLib::RequestDeviceState s;
    134 			s.type = _type;
    135 			send(bridgeLib::Command::RequestDeviceState, s);
    136 		}, [&](baseLib::BinaryStream& _in)
    137 		{
    138 			const auto& s = TcpConnection::getDeviceState().state;
    139 			_state.insert(_state.end(), s.begin(), s.end());
    140 		}, bridgeLib::Command::DeviceState);
    141 	}
    142 
    143 	void DeviceConnection::handleDeviceState(baseLib::BinaryStream& _in)
    144 	{
    145 		TcpConnection::handleDeviceState(_in);
    146 		m_handleReplyFunc(bridgeLib::Command::DeviceState, _in);
    147 	}
    148 
    149 	bool DeviceConnection::setDeviceState(const std::vector<uint8_t>& _state, const synthLib::StateType _type)
    150 	{
    151 		if(_state.empty())
    152 			return false;
    153 
    154 		auto& s = TcpConnection::getDeviceState();
    155 		s.state = _state;
    156 		s.type = _type;
    157 
    158 		sendAwaitReply([&]
    159 		{
    160 			send(bridgeLib::Command::DeviceState, s);
    161 		}, [](baseLib::BinaryStream&)
    162 		{
    163 		}, bridgeLib::Command::DeviceInfo);
    164 		return true;
    165 	}
    166 
    167 	void DeviceConnection::setSamplerate(const float _samplerate)
    168 	{
    169 		sendAwaitReply([&]
    170 		{
    171 			bridgeLib::SetSamplerate sr;
    172 			sr.samplerate = _samplerate;
    173 			send(bridgeLib::Command::SetSamplerate, sr);
    174 		}, [&](baseLib::BinaryStream&)
    175 		{
    176 		}, bridgeLib::Command::DeviceInfo);
    177 	}
    178 
    179 	void DeviceConnection::setStateFromUnknownCustomData(const std::vector<uint8_t>& _state)
    180 	{
    181 		sendAwaitReply([&]
    182 		{
    183 			bridgeLib::SetUnknownCustomData d;
    184 			d.data = _state;
    185 			send(bridgeLib::Command::SetUnknownCustomData, d);
    186 		}, [&](baseLib::BinaryStream&)
    187 		{
    188 		}, bridgeLib::Command::DeviceInfo);
    189 	}
    190 
    191 	void DeviceConnection::setDspClockPercent(const uint32_t _percent)
    192 	{
    193 		sendAwaitReply([&]
    194 		{
    195 			bridgeLib::SetDspClockPercent p;
    196 			p.percent = _percent;
    197 			send(bridgeLib::Command::SetDspClockPercent, p);
    198 		}, [&](baseLib::BinaryStream&)
    199 		{
    200 		}, bridgeLib::Command::DeviceInfo);
    201 	}
    202 
    203 	bool DeviceConnection::sendAwaitReply(const std::function<void()>& _send, const std::function<void(baseLib::BinaryStream&)>& _reply, const bridgeLib::Command _replyCommand)
    204 	{
    205 		bool receiveDone = false;
    206 
    207 		m_handleReplyFunc = [&](const bridgeLib::Command _command, baseLib::BinaryStream& _in)
    208 		{
    209 			if(_command != _replyCommand)
    210 				return;
    211 
    212 			_reply(_in);
    213 
    214 			{
    215 				std::unique_lock lockCv(m_cvWaitMutex);
    216 				receiveDone = true;
    217 			}
    218 			m_cvWait.notify_one();
    219 		};
    220 
    221 		_send();
    222 
    223 		std::unique_lock lockCv(m_cvWaitMutex);
    224 		m_cvWait.wait_for(lockCv, std::chrono::seconds(g_replyTimeoutSecs), [&]
    225 		{
    226 			return receiveDone;
    227 		});
    228 
    229 		m_handleReplyFunc = [](bridgeLib::Command, baseLib::BinaryStream&)
    230 		{
    231 		};
    232 
    233 		if(receiveDone)
    234 			return true;
    235 		LOG("Receive timeout, closing connection");
    236 		close();
    237 		return false;
    238 	}
    239 }