summaryrefslogtreecommitdiff
path: root/src/components/media_manager/src/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/media_manager/src/audio')
-rw-r--r--src/components/media_manager/src/audio/a2dp_source_player_adapter.cc278
-rw-r--r--src/components/media_manager/src/audio/audio_stream_sender_thread.cc149
-rw-r--r--src/components/media_manager/src/audio/from_mic_recorder_adapter.cc110
-rw-r--r--src/components/media_manager/src/audio/from_mic_recorder_listener.cc99
-rw-r--r--src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc266
-rw-r--r--src/components/media_manager/src/audio/pipe_audio_streamer_adapter.cc52
-rw-r--r--src/components/media_manager/src/audio/socket_audio_streamer_adapter.cc51
7 files changed, 1005 insertions, 0 deletions
diff --git a/src/components/media_manager/src/audio/a2dp_source_player_adapter.cc b/src/components/media_manager/src/audio/a2dp_source_player_adapter.cc
new file mode 100644
index 0000000000..91604d22c9
--- /dev/null
+++ b/src/components/media_manager/src/audio/a2dp_source_player_adapter.cc
@@ -0,0 +1,278 @@
+/**
+* Copyright (c) 2013, Ford Motor Company
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of the Ford Motor Company nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <net/if.h>
+#include <pulse/simple.h>
+#include <pulse/error.h>
+#include <string.h>
+#include <utility>
+#include "utils/threads/thread.h"
+#include "media_manager/audio/a2dp_source_player_adapter.h"
+#include "utils/lock.h"
+#include "utils/threads/thread_delegate.h"
+#include "utils/logger.h"
+#include "connection_handler/connection_handler_impl.h"
+
+namespace media_manager {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "A2DPSourcePlayerAdapter")
+
+class A2DPSourcePlayerAdapter::A2DPSourcePlayerThread
+ : public threads::ThreadDelegate {
+ public:
+ explicit A2DPSourcePlayerThread(const std::string& device);
+
+ void threadMain();
+
+ bool exitThreadMain();
+
+ private:
+ // The Sample format to use
+ static const pa_sample_spec sSampleFormat_;
+
+ pa_simple* s_in, *s_out;
+ std::string device_;
+ const int32_t BUFSIZE_;
+ bool should_be_stopped_;
+ sync_primitives::Lock should_be_stopped_lock_;
+
+ void freeStreams();
+
+ DISALLOW_COPY_AND_ASSIGN(A2DPSourcePlayerThread);
+};
+
+A2DPSourcePlayerAdapter::A2DPSourcePlayerAdapter() {
+}
+
+A2DPSourcePlayerAdapter::~A2DPSourcePlayerAdapter() {
+ for (std::map<int32_t, threads::Thread*>::iterator it = sources_.begin();
+ sources_.end() != it;
+ ++it) {
+ if (NULL != it->second) {
+ if (it->second->is_running()) {
+ it->second->stop();
+ }
+ delete(it->second);
+ }
+ }
+ sources_.clear();
+}
+
+void A2DPSourcePlayerAdapter::StartActivity(int32_t application_key) {
+ LOG4CXX_INFO(logger_, "Starting a2dp playing music for "
+ << application_key << " application.");
+ if (application_key != current_application_) {
+ current_application_ = application_key;
+
+ std::map<int32_t, threads::Thread*>::iterator it =
+ sources_.find(application_key);
+ if (sources_.end() != it) {
+ if (NULL != it->second && !it->second->is_running()) {
+ it->second->start();
+ } else {
+ current_application_ = 0;
+ }
+ } else {
+ uint32_t device_id = 0;
+ connection_handler::ConnectionHandlerImpl::instance()->
+ GetDataOnSessionKey(application_key, 0, NULL, &device_id);
+ std::string mac_adddress;
+ connection_handler::ConnectionHandlerImpl::instance()->GetDataOnDeviceID(
+ device_id,
+ NULL,
+ NULL,
+ &mac_adddress);
+
+ // TODO(PK): Convert mac_adddress to the
+ // following format : "bluez_source.XX_XX_XX_XX_XX_XX" if needed
+ // before passing to the A2DPSourcePlayerThread constructor
+
+ threads::Thread* new_activity = new threads::Thread(
+ mac_adddress.c_str(),
+ new A2DPSourcePlayerAdapter::A2DPSourcePlayerThread(mac_adddress));
+ if (NULL != new_activity) {
+ sources_.insert(std::pair<int32_t, threads::Thread*>(
+ application_key, new_activity));
+
+ new_activity->start();
+ } else {
+ current_application_ = 0;
+ }
+ }
+ }
+}
+
+void A2DPSourcePlayerAdapter::StopActivity(int32_t application_key) {
+ LOG4CXX_INFO(logger_, "Stopping 2dp playing for "
+ << application_key << " application.");
+ if (application_key != current_application_) {
+ return;
+ }
+ std::map<int32_t, threads::Thread*>::iterator it =
+ sources_.find(application_key);
+ if (sources_.end() != it) {
+ LOG4CXX_DEBUG(logger_, "Source exists.");
+ if (NULL != it->second) {
+ LOG4CXX_DEBUG(logger_, "Sources thread was allocated");
+ if ((*it).second->is_running()) {
+ // Sources thread was started - stop it
+ LOG4CXX_DEBUG(logger_, "Sources thread was started - stop it");
+ (*it).second->stop();
+ }
+ }
+ current_application_ = 0;
+ }
+}
+
+bool A2DPSourcePlayerAdapter::is_app_performing_activity(int32_t
+ application_key) {
+ return (application_key == current_application_);
+}
+
+const pa_sample_spec A2DPSourcePlayerAdapter::A2DPSourcePlayerThread::
+sSampleFormat_ = {
+ /*format*/ PA_SAMPLE_S16LE,
+ /*rate*/ 44100,
+ /*channels*/ 2
+};
+
+A2DPSourcePlayerAdapter::A2DPSourcePlayerThread::A2DPSourcePlayerThread(
+ const std::string& device)
+ : threads::ThreadDelegate(),
+ device_(device),
+ BUFSIZE_(32) {
+}
+
+void A2DPSourcePlayerAdapter::A2DPSourcePlayerThread::freeStreams() {
+ LOG4CXX_INFO(logger_, "Free streams in A2DPSourcePlayerThread.");
+ if (s_in) {
+ pa_simple_free(s_in);
+ }
+
+ if (s_out) {
+ pa_simple_free(s_out);
+ }
+}
+
+bool A2DPSourcePlayerAdapter::A2DPSourcePlayerThread::exitThreadMain() {
+ sync_primitives::AutoLock auto_lock(should_be_stopped_lock_);
+ should_be_stopped_ = true;
+ return true;
+}
+
+void A2DPSourcePlayerAdapter::A2DPSourcePlayerThread::threadMain() {
+ LOG4CXX_INFO(logger_, "Main thread of A2DPSourcePlayerThread.");
+
+ {
+ sync_primitives::AutoLock auto_lock(should_be_stopped_lock_);
+ should_be_stopped_ = false;
+ }
+
+ int32_t error;
+
+ const char* a2dpSource = device_.c_str();
+
+ LOG4CXX_DEBUG(logger_, device_);
+
+ LOG4CXX_DEBUG(logger_, "Creating streams");
+
+ /* Create a new playback stream */
+ if (!(s_out = pa_simple_new(NULL, "AudioManager", PA_STREAM_PLAYBACK, NULL,
+ "playback", &sSampleFormat_, NULL, NULL, &error))) {
+ LOG4CXX_ERROR(logger_, "pa_simple_new() failed: " << pa_strerror(error));
+ freeStreams();
+ return;
+ }
+
+ if (!(s_in = pa_simple_new(NULL, "AudioManager", PA_STREAM_RECORD, a2dpSource,
+ "record", &sSampleFormat_, NULL, NULL, &error))) {
+ LOG4CXX_ERROR(logger_, "pa_simple_new() failed: " << pa_strerror(error));
+ freeStreams();
+ return;
+ }
+
+ LOG4CXX_DEBUG(logger_, "Entering main loop");
+
+ for (;;) {
+ uint8_t buf[BUFSIZE_];
+
+ pa_usec_t latency;
+
+ if ((latency = pa_simple_get_latency(s_in, &error)) == (pa_usec_t) - 1) {
+ LOG4CXX_ERROR(logger_, "pa_simple_get_latency() failed: "
+ << pa_strerror(error));
+ break;
+ }
+
+ // LOG4CXX_INFO(logger_, "In: " << static_cast<float>(latency));
+
+ if ((latency = pa_simple_get_latency(s_out, &error)) == (pa_usec_t) - 1) {
+ LOG4CXX_ERROR(logger_, "pa_simple_get_latency() failed: "
+ << pa_strerror(error));
+ break;
+ }
+
+ // LOG4CXX_INFO(logger_, "Out: " << static_cast<float>(latency));
+
+ if (pa_simple_read(s_in, buf, sizeof(buf), &error) < 0) {
+ LOG4CXX_ERROR(logger_, "read() failed: " << strerror(error));
+ break;
+ }
+
+ /* ... and play it */
+ if (pa_simple_write(s_out, buf, sizeof(buf), &error) < 0) {
+ LOG4CXX_ERROR(logger_, "pa_simple_write() failed: "
+ << pa_strerror(error));
+ break;
+ }
+
+ bool should_be_stopped;
+ {
+ sync_primitives::AutoLock auto_lock(should_be_stopped_lock_);
+ should_be_stopped = should_be_stopped_;
+ }
+
+ if (should_be_stopped) {
+ break;
+ }
+ }
+
+ /* Make sure that every single sample was played */
+ if (pa_simple_drain(s_out, &error) < 0) {
+ LOG4CXX_ERROR(logger_, "pa_simple_drain() failed: " << pa_strerror(error));
+ freeStreams();
+ return;
+ }
+
+ freeStreams();
+}
+
+} // namespace media_manager
diff --git a/src/components/media_manager/src/audio/audio_stream_sender_thread.cc b/src/components/media_manager/src/audio/audio_stream_sender_thread.cc
new file mode 100644
index 0000000000..a3ef5af0bf
--- /dev/null
+++ b/src/components/media_manager/src/audio/audio_stream_sender_thread.cc
@@ -0,0 +1,149 @@
+//
+// Copyright (c) 2013, Ford Motor Company
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided with the
+// distribution.
+//
+// Neither the name of the Ford Motor Company nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#if defined(OS_POSIX) && defined(OS_LINUX)
+#include <pthread.h> // TODO(DK): Need to remove
+#include <unistd.h>
+#endif
+
+
+#include <string>
+#include "application_manager/application_manager_impl.h"
+#include "application_manager/mobile_command_factory.h"
+#include "application_manager/application_impl.h"
+#include "smart_objects/smart_object.h"
+#include "interfaces/MOBILE_API.h"
+#include "utils/file_system.h"
+#include "utils/logger.h"
+
+#include "media_manager/audio/audio_stream_sender_thread.h"
+#include "application_manager/smart_object_keys.h"
+#include "application_manager/message.h"
+
+namespace media_manager {
+using sync_primitives::AutoLock;
+
+const int32_t AudioStreamSenderThread::kAudioPassThruTimeout = 1;
+const uint32_t kMqueueMessageSize = 4095;
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "AudioPassThruThread")
+
+AudioStreamSenderThread::AudioStreamSenderThread(
+ const std::string fileName, uint32_t session_key)
+ : session_key_(session_key),
+ fileName_(fileName),
+ shouldBeStoped_(false),
+ shouldBeStoped_lock_(),
+ shouldBeStoped_cv_() {
+ LOG4CXX_TRACE_ENTER(logger_);
+}
+
+AudioStreamSenderThread::~AudioStreamSenderThread() {
+}
+
+void AudioStreamSenderThread::threadMain() {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ offset_ = 0;
+
+ while (false == getShouldBeStopped()) {
+ AutoLock auto_lock(shouldBeStoped_lock_);
+ shouldBeStoped_cv_.WaitFor(auto_lock, kAudioPassThruTimeout * 1000);
+ sendAudioChunkToMobile();
+ }
+
+ LOG4CXX_TRACE_EXIT(logger_);
+}
+
+void AudioStreamSenderThread::sendAudioChunkToMobile() {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ std::vector<uint8_t> binaryData;
+ std::vector<uint8_t>::iterator from;
+ std::vector<uint8_t>::iterator to;
+
+ if (!file_system::ReadBinaryFile(fileName_, binaryData)) {
+ LOG4CXX_ERROR_EXT(logger_, "Unable to read file." << fileName_);
+
+ return;
+ }
+
+ if (binaryData.empty()) {
+ LOG4CXX_ERROR_EXT(logger_, "Binary data is empty.");
+ return;
+ }
+
+ LOG4CXX_INFO_EXT(logger_, "offset = " << offset_);
+
+ from = binaryData.begin() + offset_;
+ to = binaryData.end();
+
+ if (from < binaryData.end() /*from != binaryData.end()*/) {
+ LOG4CXX_INFO_EXT(logger_, "from != binaryData.end()");
+
+ offset_ = offset_ + to - from;
+
+ application_manager::ApplicationManagerImpl::instance()->
+ SendAudioPassThroughNotification(session_key_,
+ std::vector<uint8_t>(from, to));
+ binaryData.clear();
+ }
+#if !defined(EXTENDED_MEDIA_MODE)
+ // without recording stream restart reading 1-sec file
+ offset_ = 0;
+#endif
+}
+
+bool AudioStreamSenderThread::getShouldBeStopped() {
+ AutoLock auto_lock(shouldBeStoped_lock_);
+
+ return shouldBeStoped_;
+}
+
+void AudioStreamSenderThread::setShouldBeStopped(bool should_stop) {
+ AutoLock auto_lock(shouldBeStoped_lock_);
+ shouldBeStoped_ = should_stop;
+ shouldBeStoped_cv_.NotifyOne();
+}
+
+bool AudioStreamSenderThread::exitThreadMain() {
+ LOG4CXX_INFO(logger_, "AudioStreamSenderThread::exitThreadMain");
+ setShouldBeStopped(true);
+ return true;
+}
+
+uint32_t AudioStreamSenderThread::session_key() const {
+ return session_key_;
+}
+
+} // namespace media_manager
diff --git a/src/components/media_manager/src/audio/from_mic_recorder_adapter.cc b/src/components/media_manager/src/audio/from_mic_recorder_adapter.cc
new file mode 100644
index 0000000000..ba5e7ec54a
--- /dev/null
+++ b/src/components/media_manager/src/audio/from_mic_recorder_adapter.cc
@@ -0,0 +1,110 @@
+/**
+* Copyright (c) 2013, Ford Motor Company
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of the Ford Motor Company nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include "utils/threads/thread.h"
+#include "utils/logger.h"
+#include "media_manager/audio/from_mic_to_file_recorder_thread.h"
+#include "media_manager/audio/from_mic_recorder_adapter.h"
+
+namespace media_manager {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "FromMicRecorderAdapter")
+
+FromMicRecorderAdapter::FromMicRecorderAdapter()
+ : recorder_thread_(NULL)
+ , output_file_("default_recorded_audio.wav")
+ , kDefaultDuration(1000)
+ , duration_(0) {
+ duration_ = kDefaultDuration;
+}
+
+FromMicRecorderAdapter::~FromMicRecorderAdapter() {
+ LOG4CXX_INFO(logger_, "FromMicRecorderAdapter::~FromMicRecorderAdapter()");
+ StopActivity(current_application_);
+}
+
+void FromMicRecorderAdapter::StartActivity(int32_t application_key) {
+ LOG4CXX_INFO(logger_, "FromMicRecorderAdapter::StartActivity "
+ << application_key);
+ if (application_key == current_application_) {
+ LOG4CXX_WARN(logger_, "Running recording from mic for "
+ << current_application_);
+ return;
+ }
+
+// Todd: No gstreamer recorder thread
+ if (!recorder_thread_) {
+ FromMicToFileRecorderThread* thread_delegate =
+ new FromMicToFileRecorderThread(
+ output_file_, duration_);
+ recorder_thread_ = new threads::Thread("MicrophoneRec",
+ thread_delegate);
+ }
+
+ if (NULL != recorder_thread_) {
+ recorder_thread_->start();
+ current_application_ = application_key;
+ }
+}
+
+void FromMicRecorderAdapter::StopActivity(int32_t application_key) {
+ LOG4CXX_INFO(logger_, "FromMicRecorderAdapter::StopActivity "
+ << application_key);
+ if (application_key != current_application_) {
+ LOG4CXX_WARN(logger_, "Running activity on other app key "
+ << current_application_);
+ return;
+ }
+
+ if (NULL != recorder_thread_) {
+ recorder_thread_->stop();
+ delete recorder_thread_;
+ recorder_thread_ = NULL;
+ }
+ current_application_ = 0;
+}
+
+bool FromMicRecorderAdapter::is_app_performing_activity(int32_t
+ application_key) {
+ return (application_key == current_application_);
+}
+
+void FromMicRecorderAdapter::set_output_file(const std::string& output_file) {
+ output_file_ = output_file;
+}
+
+void FromMicRecorderAdapter::set_duration(int32_t duration) {
+ duration_ = duration;
+}
+
+} // namespace media_manager
diff --git a/src/components/media_manager/src/audio/from_mic_recorder_listener.cc b/src/components/media_manager/src/audio/from_mic_recorder_listener.cc
new file mode 100644
index 0000000000..cec85ca4e6
--- /dev/null
+++ b/src/components/media_manager/src/audio/from_mic_recorder_listener.cc
@@ -0,0 +1,99 @@
+/*
+ Copyright (c) 2013, Ford Motor Company
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with the
+ distribution.
+
+ Neither the name of the Ford Motor Company nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "utils/threads/thread.h"
+#include "utils/logger.h"
+#include "media_manager/audio/from_mic_recorder_listener.h"
+#include "media_manager/audio/audio_stream_sender_thread.h"
+
+namespace media_manager {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "FromMicRecorderListener")
+
+FromMicRecorderListener::FromMicRecorderListener(
+ const std::string& file_name)
+ : reader_(NULL)
+ , file_name_(file_name) {
+}
+
+FromMicRecorderListener::~FromMicRecorderListener() {
+ if (reader_) {
+ reader_->stop();
+ delete reader_;
+ reader_ = NULL;
+ }
+}
+
+void FromMicRecorderListener::OnDataReceived(
+ int32_t application_key,
+ const DataForListener& data) {
+}
+
+void FromMicRecorderListener::OnErrorReceived(
+ int32_t application_key,
+ const DataForListener& data) {
+}
+
+void FromMicRecorderListener::OnActivityStarted(int32_t application_key) {
+ LOG4CXX_INFO(logger_, "FromMicRecorderListener::OnActivityStarted "
+ << application_key);
+ if (application_key == current_application_) {
+ return;
+ }
+ if (!reader_) {
+ AudioStreamSenderThread* thread_delegate =
+ new AudioStreamSenderThread(file_name_, application_key);
+ reader_ = new threads::Thread("RecorderSender", thread_delegate);
+ }
+ if (reader_) {
+ reader_->start();
+ current_application_ = application_key;
+ }
+}
+
+void FromMicRecorderListener::OnActivityEnded(int32_t application_key) {
+ LOG4CXX_INFO(logger_, "FromMicRecorderListener::OnActivityEnded "
+ << application_key);
+ if (application_key != current_application_) {
+ LOG4CXX_WARN(logger_, "Not performing activity on " << application_key
+ << " but on " << current_application_);
+ return;
+ }
+ if (reader_) {
+ reader_->stop();
+ delete reader_;
+ reader_ = NULL;
+ }
+ current_application_ = 0;
+}
+
+} // namespace media_manager
diff --git a/src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc b/src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc
new file mode 100644
index 0000000000..02ccd1f2b7
--- /dev/null
+++ b/src/components/media_manager/src/audio/from_mic_to_file_recorder_thread.cc
@@ -0,0 +1,266 @@
+/*
+* Copyright (c) 2014, Ford Motor Company
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*
+* Redistributions of source code must retain the above copyright notice, this
+* list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright notice,
+* this list of conditions and the following
+* disclaimer in the documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of the Ford Motor Company nor the names of its contributors
+* may be used to endorse or promote products derived from this software
+* without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "media_manager/audio/from_mic_to_file_recorder_thread.h"
+#include <unistd.h>
+#include <sstream>
+#include "utils/logger.h"
+
+namespace media_manager {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "FromMicToFileRecorderThread")
+
+GMainLoop* FromMicToFileRecorderThread::loop = NULL;
+
+FromMicToFileRecorderThread::FromMicToFileRecorderThread(
+ const std::string& output_file, int32_t duration)
+ : threads::ThreadDelegate(),
+ argc_(5),
+ oKey_("-o"),
+ tKey_("-t"),
+ sleepThread_(NULL),
+ outputFileName_(output_file) {
+ LOG4CXX_TRACE_ENTER(logger_);
+ set_record_duration(duration);
+}
+
+void FromMicToFileRecorderThread::set_output_file(
+ const std::string& output_file) {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ outputFileName_ = output_file;
+}
+
+void FromMicToFileRecorderThread::set_record_duration(int32_t duration) {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ std::stringstream stringStream;
+ stringStream << duration / 1000;
+ durationString_ = stringStream.str();
+}
+
+void FromMicToFileRecorderThread::initArgs() {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ argv_ = new gchar*[argc_];
+
+ argv_[0] = new gchar[14];
+ argv_[1] = new gchar[3];
+ argv_[2] = new gchar[outputFileName_.length() + 1];
+ argv_[3] = new gchar[3];
+ argv_[4] = new gchar[durationString_.length() + 1];
+
+ argv_[0] = const_cast<gchar*>(std::string("AudioManager").c_str());
+ argv_[1] = const_cast<gchar*>(oKey_.c_str());
+ argv_[2] = const_cast<gchar*>(outputFileName_.c_str());
+ argv_[3] = const_cast<gchar*>(tKey_.c_str());
+ argv_[4] = const_cast<gchar*>(durationString_.c_str());
+}
+
+void FromMicToFileRecorderThread::threadMain() {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ {
+ sync_primitives::AutoLock auto_lock(stopFlagLock_);
+ shouldBeStoped_ = false;
+ }
+
+ initArgs();
+
+ GstElement* pipeline;
+ GstElement* alsasrc, *wavenc, *filesink;
+ GstBus* bus;
+
+ const gchar* device = "hw:0,0";
+ gchar* outfile = NULL;
+ gint duration = -1;
+ GOptionContext* context = NULL;
+ GError* err = NULL;
+ GOptionEntry entries[] = { {
+ "device", 'd', 0, G_OPTION_ARG_FILENAME, &device,
+ "device file (Default: hw:0,0)", "SRC"
+ }, {
+ "output", 'o', 0, G_OPTION_ARG_FILENAME, &outfile,
+ "save output of the stream to DEST", "DEST"
+ }, {
+ "duration", 't', 0, G_OPTION_ARG_INT, &duration,
+ "length of time in seconds to capture", "int32_t"
+ }, {
+ NULL
+ }
+ };
+#ifndef GLIB_VERSION_2_32 // g_thread_init() does nothing since 2.32
+ if (!g_thread_supported()) {
+ g_thread_init(NULL);
+ }
+#endif
+ // Parse the arguments
+ context = g_option_context_new("-- M-AUDIO RAW");
+ g_option_context_add_main_entries(context, entries, NULL);
+ g_option_context_add_group(context, gst_init_get_option_group());
+ if (!g_option_context_parse(context, &argc_, &argv_, &err)) {
+ g_error("%s\n", err->message);
+ }
+
+ // Check for proper arguments
+ if (outfile == NULL) {
+ g_error("Must supply destination (-d FILE)\n");
+ }
+
+ LOG4CXX_TRACE(logger_, "Reading from device: " << device);
+ LOG4CXX_TRACE(logger_, "Saving pipeline output to: " << outfile);
+ LOG4CXX_TRACE(logger_, "Duration set to: " << duration);
+
+ // Initialize gstreamer and setup the main loop information
+ gst_init(&argc_, &argv_);
+
+ pipeline = gst_pipeline_new("vga2usb-h264");
+
+ // Set up error handling
+ bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
+ gst_bus_add_watch(bus,
+ reinterpret_cast<int32_t (*)(_GstBus*, _GstMessage*, void*)>
+ (recvmsg),
+ NULL);
+ gst_object_unref(bus);
+
+ // Create all of the elements to be added to the pipeline
+ alsasrc = gst_element_factory_make("alsasrc", "alsasrc0");
+ wavenc = gst_element_factory_make("wavenc", "wavenc0");
+ filesink = gst_element_factory_make("filesink", "filesink0");
+
+ // Assert that all the elements were created
+ if (!alsasrc || !wavenc || !filesink) {
+ g_error("Failed creating one or more of the pipeline elements.\n");
+ }
+
+ // Set input and output destinations
+ g_object_set(G_OBJECT(alsasrc), "device", device, NULL);
+ g_object_set(G_OBJECT(filesink), "location", outfile, NULL);
+
+ // Add the elements to the pipeline
+ gst_bin_add_many(GST_BIN(pipeline), alsasrc, wavenc, filesink, NULL);
+
+ // Link the elements
+ gst_element_link_many(alsasrc, wavenc, filesink, NULL);
+
+ gst_element_set_state(pipeline, GST_STATE_PLAYING);
+
+ LOG4CXX_TRACE(logger_, "Initializing pipeline ...");
+ while (GST_STATE(pipeline) != GST_STATE_PLAYING) {
+ LOG4CXX_TRACE(logger_, "GST_STATE(pipeline) != GST_STATE_PLAYING");
+
+ bool shouldBeStoped;
+ {
+ sync_primitives::AutoLock auto_lock(stopFlagLock_);
+ shouldBeStoped = shouldBeStoped_;
+ }
+
+ if (shouldBeStoped) {
+ return;
+ }
+ }
+
+ LOG4CXX_TRACE(logger_, "Pipeline started ...\n");
+
+ // Start up a timer for the pipeline
+ if (duration > 0) {
+ GstTimeout timeout;
+ timeout.pipeline = pipeline;
+ timeout.duration = duration;
+
+ sleepThread_ = new threads::Thread("SleepThread"
+ , new SleepThreadDelegate(timeout));
+
+ if (NULL != sleepThread_) {
+ sleepThread_->start();
+ }
+ }
+
+ loop = g_main_loop_new(NULL, FALSE);
+
+ g_main_loop_run(loop);
+
+ gst_element_set_state(pipeline, GST_STATE_NULL);
+
+ LOG4CXX_TRACE(logger_, "Deleting pipeline\n");
+ gst_object_unref(GST_OBJECT(pipeline));
+ g_main_loop_unref(loop);
+
+ loop = NULL;
+}
+
+FromMicToFileRecorderThread::SleepThreadDelegate::SleepThreadDelegate(GstTimeout
+ timeout)
+ : threads::ThreadDelegate(),
+ timeout_(timeout) {
+}
+
+void FromMicToFileRecorderThread::SleepThreadDelegate::threadMain() {
+ LOG4CXX_TRACE(logger_, "Sleep for " << timeout_.duration << " seconds");
+
+ sleep(timeout_.duration);
+
+ if (NULL != loop) {
+ if (g_main_loop_is_running(loop)) {
+ gst_element_send_event(timeout_.pipeline, gst_event_new_eos());
+ }
+ }
+}
+
+bool FromMicToFileRecorderThread::exitThreadMain() {
+ LOG4CXX_TRACE_ENTER(logger_);
+
+ if (NULL != loop) {
+ if (g_main_loop_is_running(loop)) {
+ LOG4CXX_TRACE(logger_, "Quit loop\n");
+ g_main_loop_quit(loop);
+ }
+ }
+
+ if (NULL != sleepThread_) {
+ LOG4CXX_TRACE(logger_, "Stop sleep thread\n");
+ sleepThread_->stop();
+ delete sleepThread_;
+ sleepThread_ = NULL;
+ }
+
+ LOG4CXX_TRACE(logger_, "Set should be stopped flag\n");
+ {
+ sync_primitives::AutoLock auto_lock(stopFlagLock_);
+ shouldBeStoped_ = true;
+ }
+
+ return true;
+}
+
+} // namespace media_manager
diff --git a/src/components/media_manager/src/audio/pipe_audio_streamer_adapter.cc b/src/components/media_manager/src/audio/pipe_audio_streamer_adapter.cc
new file mode 100644
index 0000000000..5faebf93d5
--- /dev/null
+++ b/src/components/media_manager/src/audio/pipe_audio_streamer_adapter.cc
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2013, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "media_manager/audio/pipe_audio_streamer_adapter.h"
+#include "config_profile/profile.h"
+#include "utils/logger.h"
+
+namespace media_manager {
+
+CREATE_LOGGERPTR_GLOBAL(logger, "PipeAudioStreamerAdapter")
+
+PipeAudioStreamerAdapter::PipeAudioStreamerAdapter() {
+ LOG4CXX_INFO(logger, "PipeAudioStreamerAdapter::PipeAudioStreamerAdapter");
+ named_pipe_path_ = profile::Profile::instance()->named_audio_pipe_path();
+
+ Init();
+}
+
+PipeAudioStreamerAdapter::~PipeAudioStreamerAdapter() {
+ LOG4CXX_INFO(logger, "PipeAudioStreamerAdapter::~PipeAudioStreamerAdapter");
+}
+
+} // namespace media_manager
diff --git a/src/components/media_manager/src/audio/socket_audio_streamer_adapter.cc b/src/components/media_manager/src/audio/socket_audio_streamer_adapter.cc
new file mode 100644
index 0000000000..eb93032e42
--- /dev/null
+++ b/src/components/media_manager/src/audio/socket_audio_streamer_adapter.cc
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2013, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config_profile/profile.h"
+#include "media_manager/audio/socket_audio_streamer_adapter.h"
+#include "utils/logger.h"
+
+namespace media_manager {
+
+CREATE_LOGGERPTR_GLOBAL(logger, "SocketAudioStreamerAdapter")
+
+SocketAudioStreamerAdapter::SocketAudioStreamerAdapter() {
+ LOG4CXX_INFO(logger, "SocketAudioStreamerAdapter::SocketAudioStreamerAdapter");
+ port_ = profile::Profile::instance()->audio_streaming_port();
+ ip_ = profile::Profile::instance()->server_address();
+
+ Init();
+}
+
+SocketAudioStreamerAdapter::~SocketAudioStreamerAdapter() {
+}
+} // namespace media_manager