/* * Copyright (C) 2008 IPTEGO GmbH * * This file is part of SEMS, a free SIP media server. * * SEMS is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. This program is released under * the GPL with the additional exemption that compiling, linking, * and/or using OpenSSL is allowed. * * For a license to use the sems software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * SEMS 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "AmAudioMixer.h" AmAudioMixer::AmAudioMixer() { sink_channel = mixer.addChannel(); sink_connector = new AmAudioMixerConnector(mixer, sink_channel, NULL, &srcsink_mut, &sinks); } AmAudioMixer::~AmAudioMixer() { mixer.removeChannel(sink_channel); for (std::map<AmAudioMixerConnector*, unsigned int>::iterator it=sources.begin(); it != sources.end(); it++) { mixer.removeChannel(it->second); delete it->first; } delete sink_connector; } AmAudio* AmAudioMixer::addSource() { srcsink_mut.lock(); unsigned int src_channel = mixer.addChannel(); // the first source will process the media in the mixer channel AmAudioMixerConnector* conn = new AmAudioMixerConnector(mixer, src_channel, sources.empty() ? sink_connector : NULL); sources[conn] = src_channel; srcsink_mut.unlock(); return conn; } void AmAudioMixer::releaseSource(AmAudio* s) { srcsink_mut.lock(); std::map<AmAudioMixerConnector*, unsigned int>::iterator it= sources.find((AmAudioMixerConnector*)s); if (it==sources.end()) { srcsink_mut.unlock(); ERROR("source [%p] is not part of this mixer.\n", s); return; } mixer.removeChannel(it->second); delete s; sources.erase(it); srcsink_mut.unlock(); } void AmAudioMixer::addSink(AmAudio* s) { srcsink_mut.lock(); sinks.insert(s); srcsink_mut.unlock(); } void AmAudioMixer::releaseSink(AmAudio* s) { srcsink_mut.lock(); sinks.erase(s); srcsink_mut.unlock(); } int AmAudioMixerConnector::get(unsigned int user_ts, unsigned char* buffer, unsigned int nb_samples) { // in fact GCP here only needed for the mixed channel mixer.GetChannelPacket(channel, user_ts, buffer, nb_samples); if ((audio_mut != NULL) && (sinks != NULL)) { audio_mut->lock(); // write to all sinks for (std::set<AmAudio*>::iterator it=sinks->begin(); it != sinks->end(); it++) { (*it)->put(user_ts, buffer, nb_samples); } audio_mut->unlock(); } return nb_samples; } int AmAudioMixerConnector::put(unsigned int user_ts, unsigned char* buffer, unsigned int size) { mixer.PutChannelPacket(channel, user_ts, buffer, size); if (mix_channel != NULL) { // we are processing the media of the mixed channel as well ShortSample mix_buffer[SIZE_MIX_BUFFER]; mix_channel->get(user_ts, (unsigned char*)mix_buffer, size); } return size; }