/** * This file is a part of Promoe, an XMMS2 Client. * * Copyright (C) 2005-2010 XMMS2 Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ #include "volumehandler.h" #include "xclient.h" #include #include struct volumes { int left; int right; }; // The balance calculation still need some tweaking, as modifying volume // also changes balance (towards 0). So changing volume multiple times causes // balance to be reset to center static int calcBalance (int left, int right) { if (left == right) return 0; if (left == 0) return MAX_STEREO_BALANCE; if (right == 0) return -MAX_STEREO_BALANCE; double tmp = static_cast(right-left) / static_cast(qMax(left, right)); tmp *= static_cast(MAX_STEREO_BALANCE); tmp += 0.5; return static_cast(tmp); } static struct volumes calcVolumes (int volume, int balance) { struct volumes vols = {volume, volume}; if (balance == 0) { return vols; } if (balance >= MAX_STEREO_BALANCE) { vols.left = 0; return vols; } if (balance <= -MAX_STEREO_BALANCE) { vols.right = 0; return vols; } int dec = (static_cast(volume) / static_cast(MAX_STEREO_BALANCE) * static_cast(qAbs(balance))) + 0.5; if (balance > 0) { vols.left -= dec; } else { vols.right -= dec; } return vols; } VolumeHandler::VolumeHandler(const XClient *client) : QObject(), m_client (client) { m_balance = 0; m_volume = 0; keys_left << "left"; keys_right << "right"; connect (m_client->xplayback (), SIGNAL(volumeChanged(VolumeMap)), this, SLOT(serverVolumeChanged (VolumeMap))); } void VolumeHandler::serverVolumeChanged (VolumeMap volumes) { if (m_volumes.size () <= 1 && volumes.size () > 1) { emit mono(false); } if (m_volumes.size () > 1 && volumes.size () <= 1) { emit mono(true); } m_volumes = volumes; int _balance = 0; int _volume = 0; if (volumes.isEmpty()) { channel_left_mono = QString (); channel_right = QString (); } else if (isMono ()) { channel_left_mono = m_volumes.keys ().first (); channel_right = QString (); _volume = m_volumes.value (channel_left_mono); } else { channel_left_mono = channel_right = QString (); QStringList keys = m_volumes.keys (); foreach (QString lkey, keys) { if (keys_left.contains (lkey)) { channel_left_mono = lkey; break; } } foreach (QString rkey, keys) { if (keys_right.contains (rkey)) { channel_right = rkey; break; } } if (channel_left_mono.isEmpty () || channel_right.isEmpty ()) { qWarning () << "Could not parse left and right volume from: " << keys; } else { int lvalue = m_volumes.value(channel_left_mono); int rvalue = m_volumes.value(channel_right); _volume = qMax (lvalue, rvalue); _balance = calcBalance (lvalue, rvalue); } } if (_volume != m_volume) { m_volume = _volume; emit volume(_volume); } if (_balance != m_balance) { m_balance = _balance; emit balance(m_balance); } } void VolumeHandler::setVolume (QString key, int volume) { if (key.isEmpty ()) return; if (!m_volumes.contains (key)) return; if (m_volumes.value (key) == volume) return; m_client->xplayback ()->setVolume (key, volume); } void VolumeHandler::setVolume (int _volume, int _balance) { if (m_volumes.isEmpty ()) return; if (isMono ()) _balance = 0; if (_volume == m_volume && _balance == m_balance) return; const struct volumes vols = calcVolumes (_volume, _balance); setVolume (channel_left_mono, vols.left); setVolume (channel_right, vols.right); } // calculate volumes for left and right and set them in the server void VolumeHandler::setVolume (int volume) { setVolume (volume, m_balance); } // calculate volumes for left and right and set them in the server void VolumeHandler::setBalance (int balance) { setVolume (m_volume, balance); } #include "volumehandler.moc"