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

n2xLcd.cpp (3166B)


      1 #include "n2xLcd.h"
      2 
      3 #include "n2xController.h"
      4 #include "n2xEditor.h"
      5 
      6 namespace n2xJucePlugin
      7 {
      8 	constexpr char space = 0x21;	// unit separator, i.e. full width space
      9 
     10 	constexpr uint32_t g_animDelayStart = 1000;
     11 	constexpr uint32_t g_animDelayScroll = 500;
     12 	constexpr uint32_t g_animDelayEnd = 1000;
     13 
     14 	Lcd::Lcd(Editor& _editor) : m_editor(_editor)
     15 	{
     16 		m_label = _editor.findComponentT<juce::Label>("PatchName");
     17 		setText("---");
     18 
     19 		m_onProgramChanged.set(_editor.getN2xController().onProgramChanged, [this]
     20 		{
     21 			onProgramChanged();
     22 		});
     23 
     24 		m_onPartChanged.set(_editor.getN2xController().onCurrentPartChanged, [this](const uint8_t&)
     25 		{
     26 			onProgramChanged();
     27 		});
     28 	}
     29 
     30 	void Lcd::setText(const std::string& _text)
     31 	{
     32 		if(m_text == _text)
     33 			return;
     34 		m_text = _text;
     35 
     36 		if(m_overrideText.empty())
     37 			onTextChanged();
     38 	}
     39 
     40 	void Lcd::timerCallback()
     41 	{
     42 		stopTimer();
     43 
     44 		switch(m_animState)
     45 		{
     46 		case AnimState::Start:
     47 			if(updateClippedText(getCurrentText(), ++m_currentOffset))
     48 			{
     49 				m_animState = AnimState::Scroll;
     50 				startTimer(g_animDelayScroll);
     51 			}
     52 			break;
     53 		case AnimState::Scroll:
     54 			if(!updateClippedText(getCurrentText(), ++m_currentOffset))
     55 			{
     56 				m_animState = AnimState::End;
     57 				startTimer(g_animDelayEnd);
     58 			}
     59 			else
     60 			{
     61 				startTimer(g_animDelayScroll);
     62 			}
     63 			break;
     64 		case AnimState::End:
     65 			m_animState = AnimState::Start;
     66 			m_currentOffset = 0;
     67 			updateClippedText(getCurrentText(), m_currentOffset);
     68 			startTimer(g_animDelayStart);
     69 			break;
     70 		}
     71 	}
     72 
     73 	void Lcd::updatePatchName()
     74 	{
     75 		onProgramChanged();
     76 	}
     77 
     78 	void Lcd::setOverrideText(const std::string& _text)
     79 	{
     80 		std::string t = _text;
     81 		if(!t.empty())
     82 		{
     83 			while(t.size() < 3)
     84 				t = ' ' + t;
     85 		}
     86 
     87 		if(t == m_overrideText)
     88 			return;
     89 		m_overrideText = t;
     90 		onTextChanged();
     91 	}
     92 
     93 	void Lcd::setClippedText(const std::string& _text)
     94 	{
     95 		if(m_clippedText == _text)
     96 			return;
     97 		m_clippedText = _text;
     98 
     99 		auto t = _text;
    100 
    101 		for (char& c : t)
    102 		{
    103 			if(c == ' ')
    104 				c = space;
    105 		}
    106 
    107 		m_label->setText(t, juce::dontSendNotification);
    108 	}
    109 
    110 	std::string Lcd::substring(const std::string& _text, uint32_t _offset, uint32_t _len)
    111 	{
    112 		auto findIndex = [&_text](const uint32_t _off)
    113 		{
    114 			uint32_t o = _off;
    115 
    116 			for(uint32_t i=0; i<_text.size(); ++i)
    117 			{
    118 				if(_text[i] == '.' && i < o)
    119 					++o;
    120 			}
    121 			return o;
    122 		};
    123 
    124 		const auto start = findIndex(_offset);
    125 		const auto end = findIndex(_offset + _len);
    126 
    127 		return _text.substr(start, end - start);
    128 	}
    129 
    130 	bool Lcd::updateClippedText(const std::string& _text, const uint32_t _offset)
    131 	{
    132 		const auto str = substring(_text, _offset, 3);
    133 		if(str.size() < 3)
    134 			return false;
    135 		setClippedText(str);
    136 		return true;
    137 	}
    138 
    139 	void Lcd::startAnim()
    140 	{
    141 		m_currentOffset = 0;
    142 		m_animState = AnimState::Start;
    143 		startTimer(g_animDelayStart);
    144 	}
    145 
    146 	void Lcd::onTextChanged()
    147 	{
    148 		updateClippedText(getCurrentText(), 0);
    149 
    150 		if(m_clippedText != getCurrentText())
    151 		{
    152 			startAnim();
    153 		}
    154 		else
    155 		{
    156 			stopTimer();
    157 		}
    158 	}
    159 
    160 	void Lcd::onProgramChanged()
    161 	{
    162 		setText(m_editor.getCurrentPatchName());
    163 	}
    164 
    165 	const std::string& Lcd::getCurrentText() const
    166 	{
    167 		if(m_overrideText.empty())
    168 			return m_text;
    169 		return m_overrideText;
    170 	}
    171 }