[haiku-commits] haiku: hrev48668 - src/kits/media headers/private/media src/apps/soundrecorder

  • From: hamishm53@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 12 Jan 2015 19:33:29 +0100 (CET)

hrev48668 adds 2 changesets to branch 'master'
old head: 3395fdcd6ab08d881ee3bfbb50413eb1c445595d
new head: 683cf2ff58b85b9224cd8a7e08310c2b1041b952
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=683cf2f+%5E3395fdc

----------------------------------------------------------------------------

739fd34: Replace SoundCounsumer with modified BMediaRecorder.
  
  Signed-off-by: Hamish Morrison <hamishm53@xxxxxxxxx>

                                          [ Barrett <b.vitruvio@xxxxxxxxx> ]

683cf2f: BMediaRecorder: fix a few issues, fix style, remove unused SoundUtils
  
  * Use the preferred time source (GetTimeSource) for the node
  * Fix node releasing when creating the connection fails
  * Add virtual slots and padding
  * Refactor _Connect method

                                   [ Hamish Morrison <hamishm53@xxxxxxxxx> ]

----------------------------------------------------------------------------

11 files changed, 1075 insertions(+), 1134 deletions(-)
headers/private/media/MediaRecorder.h     | 118 +++++
headers/private/media/MediaRecorderNode.h | 115 +++++
headers/private/media/SoundConsumer.h     | 151 ------
headers/private/media/SoundUtils.h        |  56 ---
src/apps/soundrecorder/RecorderWindow.cpp | 184 +++----
src/apps/soundrecorder/RecorderWindow.h   |  16 +-
src/kits/media/Jamfile                    |   4 +-
src/kits/media/MediaRecorder.cpp          | 434 ++++++++++++++++
src/kits/media/MediaRecorderNode.cpp      | 324 ++++++++++++
src/kits/media/SoundConsumer.cpp          | 700 --------------------------
src/kits/media/SoundUtils.cpp             | 107 ----

############################################################################

Commit:      739fd34cf534560c5bf171ec6e414b85532c1bda
URL:         http://cgit.haiku-os.org/haiku/commit/?id=739fd34
Author:      Barrett <b.vitruvio@xxxxxxxxx>
Date:        Sun May  4 19:44:00 2014 UTC
Committer:   Hamish Morrison <hamishm53@xxxxxxxxx>
Commit-Date: Mon Jan 12 18:31:20 2015 UTC

Replace SoundCounsumer with modified BMediaRecorder.

Signed-off-by: Hamish Morrison <hamishm53@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/headers/private/media/MediaRecorder.h 
b/headers/private/media/MediaRecorder.h
new file mode 100644
index 0000000..8b6d54e
--- /dev/null
+++ b/headers/private/media/MediaRecorder.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2014, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _MEDIA_RECORDER_H
+#define _MEDIA_RECORDER_H
+
+
+#include <MediaNode.h>
+#include <TimeSource.h>
+
+#include "MediaRecorderNode.h"
+#include "SoundUtils.h"
+
+
+namespace BPrivate { namespace media {
+
+class BMediaRecorder {
+public:
+                                                               
BMediaRecorder(const char* name,
+                                                                       
media_type type
+                                                                               
= B_MEDIA_UNKNOWN_TYPE);
+
+       virtual                                         ~BMediaRecorder();
+
+                       status_t                        InitCheck() const;
+
+       typedef void                            (*ProcessFunc)(void* cookie,
+                                                                       
bigtime_t timestamp, void* data,
+                                                                       size_t 
datasize,
+                                                                       const 
media_format& format);
+
+       typedef void                            (*NotifyFunc)(void* cookie,
+                                                                       int32 
code, ...);
+
+                       status_t                        SetHooks(ProcessFunc 
recordFunc = NULL,
+                                                                       
NotifyFunc notifyFunc = NULL,
+                                                                       void* 
cookie = NULL);
+
+                       void                            SetAcceptedFormat(
+                                                                       const 
media_format& format);
+
+       virtual status_t                        Start(bool force = false);
+       virtual status_t                        Stop(bool force = false);
+
+       virtual status_t                        Connect(const media_format& 
format,
+                                                                       uint32 
flags = 0);
+
+       virtual status_t                        Connect(const 
dormant_node_info& dormantInfo,
+                                                                       const 
media_format* format = NULL,
+                                                                       uint32 
flags = 0);
+
+       virtual status_t                        Connect(const media_node& node,
+                                                                       const 
media_output* useOutput = NULL,
+                                                                       const 
media_format* format = NULL,
+                                                                       uint32 
flags = 0);
+
+       virtual status_t                        Disconnect();
+
+                       bool                            IsConnected() const;
+                       bool                            IsRunning() const;
+
+                       const media_format&     Format() const;
+
+                       const media_output&     MediaOutput() const;
+                       const media_input&      MediaInput() const;
+
+protected:
+
+       virtual void                            BufferReceived(void* buffer,
+                                                                       size_t 
size,
+                                                                       const 
media_header& header);
+private:
+
+               status_t                                _Connect(
+                                                                       const 
media_format* format,
+                                                                       uint32 
flags,
+                                                                       const 
dormant_node_info* dormantNode,
+                                                                       const 
media_node* mediaNode,
+                                                                       const 
media_output* output);
+
+               status_t                                fInitErr;
+
+               bool                                    fConnected;
+               bool                                    fRunning;
+
+               BTimeSource*                    fTimeSource;
+
+               ProcessFunc                             fRecordHook;
+               NotifyFunc                              fNotifyHook;
+
+               media_node                              fOutputNode;
+               media_output                    fOutput;
+
+               BMediaRecorderNode*             fNode;
+               media_input                             fInput;
+
+               void*                                   fBufferCookie;
+
+               friend class                    BMediaRecorderNode;
+};
+
+}
+
+}
+
+using namespace BPrivate::media;
+
+#endif //      _MEDIA_RECORDER_H
diff --git a/headers/private/media/MediaRecorderNode.h 
b/headers/private/media/MediaRecorderNode.h
new file mode 100644
index 0000000..b1e421e
--- /dev/null
+++ b/headers/private/media/MediaRecorderNode.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 1999, Be Incorporated
+ * Copyright 2014, Dario Casalinuovo
+ * All Rights Reserved.
+ * This file may be used under the terms of the Be Sample Code License.
+ */
+#ifndef _MEDIA_RECORDER_NODE_H
+#define _MEDIA_RECORDER_NODE_H
+
+
+#include <BufferConsumer.h>
+#include <MediaEventLooper.h>
+#include <String.h>
+
+
+namespace BPrivate { namespace media {
+
+class BMediaRecorder;
+
+class BMediaRecorderNode : public BMediaEventLooper,
+       public BBufferConsumer {
+public:
+                                                       
BMediaRecorderNode(const char* name,
+                                                               BMediaRecorder* 
recorder,
+                                                               media_type type
+                                                                       = 
B_MEDIA_UNKNOWN_TYPE);
+
+                       //      TODO these are not thread safe; we should fix 
that...
+                       void                    SetAcceptedFormat(const 
media_format& format);
+
+                       status_t                GetInput(media_input* outInput);
+
+                       void                    SetDataEnabled(bool enabled);
+
+protected:
+
+       virtual BMediaAddOn*    AddOn(int32* id) const;
+
+       virtual void                    NodeRegistered();
+
+       virtual void                    SetRunMode(run_mode mode);
+
+       virtual void                    HandleEvent(const media_timed_event* 
event,
+                                                               bigtime_t 
lateness,
+                                                               bool 
realTimeEvent);
+
+       virtual void                    Start(bigtime_t performanceTime);
+
+       virtual void                    Stop(bigtime_t performanceTime,
+                                                               bool immediate);
+
+       virtual void                    Seek(bigtime_t mediaTime,
+                                                               bigtime_t 
performanceTime);
+
+       virtual void                    TimeWarp(bigtime_t realTime,
+                                                               bigtime_t 
performanceTime);
+
+       virtual status_t                HandleMessage(int32 message,
+                                                               const void* 
data,
+                                                               size_t size);
+
+                       // Someone, probably the producer, is asking you about
+                       // this format. Give your honest opinion, possibly
+                       // modifying *format. Do not ask upstream producer about
+                       //      the format, since he's synchronously waiting 
for your
+                       // reply.
+
+       virtual status_t                AcceptFormat(const media_destination& 
dest,
+                                                               media_format* 
format);
+
+       virtual status_t                GetNextInput(int32* cookie,
+                                                               media_input* 
outInput);
+
+       virtual void                    DisposeInputCookie(int32 cookie);
+
+       virtual void                    BufferReceived(BBuffer* buffer);
+
+       virtual void                    ProducerDataStatus(
+                                                               const 
media_destination& forWhom,
+                                                               int32 status,
+                                                               bigtime_t 
performanceTime);
+
+       virtual status_t                GetLatencyFor(
+                                                               const 
media_destination& forWhom,
+                                                               bigtime_t*  
outLatency,
+                                                               media_node_id*  
outTimesource);
+
+       virtual status_t                Connected(
+                                                               const 
media_source& producer,
+                                                               const 
media_destination& where,
+                                                               const 
media_format& withFormat,
+                                                               media_input* 
outInput);
+
+       virtual void                    Disconnected(
+                                                               const 
media_source& producer,
+                                                               const 
media_destination& where);
+
+       virtual status_t                FormatChanged(
+                                                               const 
media_source& producer,
+                                                               const 
media_destination& consumer,
+                                                               int32 tag,
+                                                               const 
media_format& format);
+
+protected:
+
+       virtual                                 ~BMediaRecorderNode();
+
+                       BMediaRecorder* fRecorder;
+                       media_format    fOKFormat;
+                       media_input             fInput;
+                       BString                 fName;
+};
+
+}
+}
+
+using namespace BPrivate::media;
+
+#endif //      _MEDIA_RECORDER_NODE_H
diff --git a/headers/private/media/SoundConsumer.h 
b/headers/private/media/SoundConsumer.h
deleted file mode 100644
index c51dcc3..0000000
--- a/headers/private/media/SoundConsumer.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*******************************************************************************
-/
-/      File:                   SoundConsumer.h
-/
-/   Description:       Record sound from some sound-producing Node.
-/
-/      Copyright 1998, Be Incorporated, All Rights Reserved
-/
-*******************************************************************************/
-#ifndef        SOUND_CONSUMER_H
-#define SOUND_CONSUMER_H
-
-//     To use this Consumer:
-//     1. Create Record and Notify hooks, or subclass SoundConsumer
-//        if you'd rather use the inheritance hierarchy.
-//        * The Record function should do whatever you want to do
-//          when you receive a buffer.
-//        * The Notify function should handle whatever events
-//          you wish to handle (defined in SoundUtil.h).
-//     2: Create an instance of SoundConsumer, giving it the
-//        appropriate hook functions. Or, create an instance of an
-//        appropriate subclass if you've made one.
-//     3: Register your new Consumer with the MediaRoster.
-//     4: Connect your Consumer to some Producer.
-//     5: Start or Stop the Consumer if your hook functions
-//        implement behavior for these kinds of events.
-//        Seek the Consumer to set the offset of the timestamps that
-//        your Record function will see.
-//     6: When you're done, disconnect the Consumer, then delete it.
-
-#include <BufferConsumer.h>
-#include "SoundUtils.h"
-
-namespace BPrivate {
-
-
-class SoundConsumer : public BBufferConsumer {
-public:
-                                                               
SoundConsumer(const char* name,
-                                                                       
SoundProcessFunc recordFunc = NULL,
-                                                                       
SoundNotifyFunc notifyFunc = NULL,
-                                                                       void* 
cookie = NULL);
-       virtual                                         ~SoundConsumer();
-
-       //This function is OK to call from any thread.
-                       status_t                        
SetHooks(SoundProcessFunc recordFunc = NULL,
-                                                                       
SoundNotifyFunc notifyFunc = NULL,
-                                                                       void* 
cookie = NULL);
-
-       //      The MediaNode interface
-public:
-       virtual port_id                         ControlPort() const;
-       virtual BMediaAddOn*            AddOn(int32* internalID) const;
-               // Who instantiated you -- or NULL for app class
-
-
-protected:
-       virtual void                            Start(bigtime_t 
performanceTime);
-       virtual void                            Stop(bigtime_t performanceTime, 
bool immediate);
-       virtual void                            Seek(bigtime_t mediaTime,
-                                                                       
bigtime_t performanceTime);
-       virtual void                            SetRunMode(run_mode mode);
-       virtual void                            TimeWarp(bigtime_t atRealTime,
-                                                                       
bigtime_t to_performanceTime);
-       virtual void                            Preroll();
-       virtual void                            SetTimeSource(BTimeSource* 
timeSource);
-       virtual status_t                        HandleMessage(int32 message, 
const void* data,
-                                                                       size_t 
size);
-
-       //      The BufferConsumer interface
-       virtual status_t                        AcceptFormat(const 
media_destination& dest,
-                                                                       
media_format* format);
-       virtual status_t                        GetNextInput(int32* cookie,
-                                                                       
media_input* _input);
-       virtual void                            DisposeInputCookie(int32 
cookie);
-       virtual void                            BufferReceived(BBuffer* buffer);
-       virtual void                            ProducerDataStatus(
-                                                                       const 
media_destination& forWhom,
-                                                                       int32 
status, bigtime_t atMediaTime);
-       virtual status_t                        GetLatencyFor(const 
media_destination& forWhom,
-                                                                       
bigtime_t* _latency,
-                                                                       
media_node_id* _timesource);
-       virtual status_t                        Connected(const media_source& 
producer,
-                                                                       const 
media_destination& where,
-                                                                       const 
media_format& format,
-                                                                       
media_input* _input);
-       virtual void                            Disconnected(const 
media_source& producer,
-                                                                       const 
media_destination& where);
-       virtual status_t                        FormatChanged(const 
media_source& producer,
-                                                                       const 
media_destination& consumer, 
-                                                                       int32 
fromChangeCount,
-                                                                       const 
media_format& format);
-
-protected:
-       //      Functions called when no hooks are installed.
-       //      OK to override instead of installing hooks.
-       virtual void                            Record(bigtime_t time, const 
void* data,
-                                                                       size_t 
size,
-                                                                       const 
media_raw_audio_format& format);
-       virtual void                            Notify(int32 cause, ...);
-
-private:
-                       SoundProcessFunc        m_recordHook;
-                       SoundNotifyFunc         m_notifyHook;
-                       void*                           m_cookie;
-                       media_input                     m_input;
-                       thread_id                       m_thread;
-                       port_id                         m_port;
-
-       // The times we need to deal with
-       // My notation for times: tr = real time,
-       // tp = performance time, tm = media time.
-                       bigtime_t                       m_trTimeout;
-                               // how long to wait on the input port
-                       bigtime_t                       m_tpSeekAt;
-                               // when we Seek
-                       bigtime_t                       m_tmSeekTo;
-                               // target time for Seek
-
-       // The transformation from media to peformance time.
-       // d = p - m, so m + d = p.
-       // Media time is generally governed by the Seek
-       // function. In our node, we simply use media time as
-       // the time that we report to the record hook function.
-       // If we were a producer node, we might use media time
-       // to track where we were in playing a certain piece
-       // of media. But we aren't.
-                       bigtime_t                       m_delta;
-               
-       // State variables
-                       bool                            m_seeking;
-                               // a Seek is pending
-
-       //      Functions to calculate timing values. OK to override.
-       //      ProcessingLatency is the time it takes to process a buffer;
-       //      TotalLatency is returned to producer; Timeout is passed
-       //      to call to read_port_etc() in service thread loop.
-       virtual bigtime_t                       Timeout();
-       virtual bigtime_t                       ProcessingLatency();
-       virtual bigtime_t                       TotalLatency();
-       //      The actual thread doing the work
-       static  status_t                        ThreadEntry(void* cookie);
-                       void                            ServiceThread();
-                       void                            DoHookChange(void* 
message);
-};
-
-
-}
-
-
-#endif // SOUND_CONSUMER_H
diff --git a/src/apps/soundrecorder/RecorderWindow.cpp 
b/src/apps/soundrecorder/RecorderWindow.cpp
index 7445ff9..a4dbf8a 100644
--- a/src/apps/soundrecorder/RecorderWindow.cpp
+++ b/src/apps/soundrecorder/RecorderWindow.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright 2005, Jérôme Duval. All rights reserved.
+ * Copyright 2014, Dario Casalinuovo. All rights reserved.
  * Distributed under the terms of the MIT License.
  *
  * Inspired by SoundCapture from Be newsletter (Media Kit Basics:
@@ -42,8 +43,8 @@
 #include <TimeSource.h>
 #include <NodeInfo.h>
 
+#include "SoundUtils.h"
 #include "RecorderWindow.h"
-#include "SoundConsumer.h"
 #include "FileUtils.h"
 
 #if ! NDEBUG
@@ -123,7 +124,7 @@ RecorderWindow::RecorderWindow()
        fSaveButton = NULL;
        fLoopButton = NULL;
        fInputField = NULL;
-       fRecordNode = 0;
+       fRecorder = NULL;
        fRecording = false;
        fTempCount = -1;
        fButtonState = btnPaused;
@@ -146,14 +147,15 @@ RecorderWindow::RecorderWindow()
 
 RecorderWindow::~RecorderWindow()
 {
-       //      The sound consumer and producer are Nodes; it has to be 
released and the Roster
-       //      will reap it when it's done.
-       if (fRecordNode)
-               fRecordNode->Release();
+       //  The MediaRecorder have to be deleted, the dtor
+       //  disconnect it from the media_kit.
+       delete fRecorder;
+
        delete fPlayer;
 
        if (fPlayTrack && fPlayFile)
                fPlayFile->ReleaseTrack(fPlayTrack);
+
        if (fPlayFile)
                delete fPlayFile;
        fPlayTrack = NULL;
@@ -232,17 +234,25 @@ RecorderWindow::InitWindow()
                if (error < B_OK) //    there's no mixer?
                        goto bad_mojo;
 
-               //      Create our internal Node which records sound, and 
register it.
-               fRecordNode = new SoundConsumer("Sound Recorder");
-               error = fRoster->RegisterNode(fRecordNode);
-               if (error < B_OK)
+               fRecorder = new BMediaRecorder("Sound Recorder",
+                       B_MEDIA_RAW_AUDIO);
+
+               if (fRecorder->InitCheck() < B_OK)
                        goto bad_mojo;
 
+               // Set the node to accept only audio data
+               media_format output_format;
+               output_format.type = B_MEDIA_RAW_AUDIO;
+               output_format.u.raw_audio = media_raw_audio_format::wildcard;
+               fRecorder->SetAcceptedFormat(output_format);
+
                //      Create the window header with controls
                BRect r(Bounds());
                r.bottom = r.top + 175;
-               BBox *background = new BBox(r, "_background", 
B_FOLLOW_LEFT_RIGHT
-                       | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS | 
B_NAVIGABLE_JUMP, B_NO_BORDER);
+               BBox *background = new BBox(r, "_background",
+                       B_FOLLOW_LEFT_RIGHT     | B_FOLLOW_TOP, B_WILL_DRAW
+                       | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, B_NO_BORDER);
+
                AddChild(background);
 
                r = background->Bounds();
@@ -451,9 +461,7 @@ RecorderWindow::InitWindow()
                dormant_node_info dni[maxInputCount];
 
                int32 real_count = maxInputCount;
-               media_format output_format;
-               output_format.type = B_MEDIA_RAW_AUDIO;
-               output_format.u.raw_audio = media_raw_audio_format::wildcard;
+
                error = fRoster->GetDormantNodes(dni, &real_count, 0, 
&output_format,
                        0, B_BUFFER_PRODUCER | B_PHYSICAL_INPUT);
                if (real_count > maxInputCount) {
@@ -514,8 +522,8 @@ RecorderWindow::InitWindow()
 bad_mojo:
        if (error >= 0)
                error = B_ERROR;
-       if (fRecordNode)
-               fRecordNode->Release();
+       if (fRecorder)
+               delete fRecorder;
 
        delete fPlayer;
        if (!fInputField)
@@ -696,14 +704,7 @@ RecorderWindow::Record(BMessage * message)
                return;
        }
 
-       //      And get it going...
-       bigtime_t then = fRecordNode->TimeSource()->Now() + 50000LL;
-       fRoster->StartNode(fRecordNode->Node(), then);
-       if (fAudioInputNode.kind & B_TIME_SOURCE) {
-               fRoster->StartNode(fAudioInputNode,
-                       fRecordNode->TimeSource()->RealTimeFor(then, 0));
-       } else
-               fRoster->StartNode(fAudioInputNode, then);
+       fRecorder->Start();
 }
 
 
@@ -871,93 +872,60 @@ RecorderWindow::MakeRecordConnection(const media_node & 
input)
 {
        CONNECT((stderr, "RecorderWindow::MakeRecordConnection()\n"));
 
-       //      Find an available output for the given input node.
-       int32 count = 0;
-       status_t err = fRoster->GetFreeOutputsFor(input, &fAudioOutput, 1, 
&count, B_MEDIA_RAW_AUDIO);
-       if (err < B_OK) {
-               CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
-                       " couldn't get free outputs from audio input node\n"));
-               return err;
-       }
-       if (count < 1) {
-               CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
-                       " no free outputs from audio input node\n"));
-               return B_BUSY;
-       }
+       status_t err = B_OK;
+       media_output audioOutput;
 
-       //      Find an available input for our own Node. Note that we go 
through the
-       //      MediaRoster; calling Media Kit methods directly on Nodes in our 
app is
-       //      not OK (because synchronization happens in the service thread, 
not in
-       //      the calling thread).
-       // TODO: explain this
-       err = fRoster->GetFreeInputsFor(fRecordNode->Node(), &fRecInput, 1, 
&count, B_MEDIA_RAW_AUDIO);
-       if (err < B_OK) {
-               CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
-                       " couldn't get free inputs for sound recorder\n"));
-               return err;
-       }
-       if (count < 1) {
-               CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
-                       " no free inputs for sound recorder\n"));
-               return B_BUSY;
-       }
+       if (!fRecorder->IsConnected()) {
+               //      Find an available output for the given input node.
+               int32 count = 0;
+               err = fRoster->GetFreeOutputsFor(input, &audioOutput, 1,
+                       &count, B_MEDIA_RAW_AUDIO);
 
-       //      Find out what the time source of the input is.
-       //      For most nodes, we just use the preferred time source (the DAC) 
for synchronization.
-       //      However, nodes that record from an input need to synchronize to 
the audio input node
-       //      instead for best results.
-       //      MakeTimeSourceFor gives us a "clone" of the time source node 
that we can manipulate
-       //      to our heart's content. When we're done with it, though, we 
need to call Release()
-       //      on the time source node, so that it keeps an accurate reference 
count and can delete
-       //      itself when it's no longer needed.
-       // TODO: what about filters connected to audio input?
-       media_node use_time_source;
-       BTimeSource * tsobj = fRoster->MakeTimeSourceFor(input);
-       if (! tsobj) {
-               CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
-                       " couldn't clone time source from audio input node\n"));
-               return B_MEDIA_BAD_NODE;
-       }
+               if (err < B_OK) {
+                       CONNECT((stderr, 
"RecorderWindow::MakeRecordConnection():"
+                               " couldn't get free outputs from audio input 
node\n"));
+                       return err;
+               }
 
-       //      Apply the time source in effect to our own Node.
-       err = fRoster->SetTimeSourceFor(fRecordNode->Node().node, 
tsobj->Node().node);
-       if (err < B_OK) {
+               if (count < 1) {
+                       CONNECT((stderr, 
"RecorderWindow::MakeRecordConnection():"
+                               " no free outputs from audio input node\n"));
+                       return B_BUSY;
+               }
+
+       } else {
                CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
-                       " couldn't set the sound recorder's time source\n"));
-               tsobj->Release();
-               return err;
+                       " audio input node already connected\n"));
+
+               return B_BUSY;
        }
 
        //      Get a format, any format.
-       fRecordFormat.u.raw_audio = fAudioOutput.format.u.raw_audio;
+       fRecordFormat.u.raw_audio = audioOutput.format.u.raw_audio;
        fRecordFormat.type = B_MEDIA_RAW_AUDIO;
 
        //      Tell the consumer where we want data to go.
-       err = fRecordNode->SetHooks(RecordFile, NotifyRecordFile, this);
+       err = fRecorder->SetHooks(RecordFile, NotifyRecordFile, this);
+
        if (err < B_OK) {
                CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
                        " couldn't set the sound recorder's hook functions\n"));
-               tsobj->Release();
                return err;
        }
 
-       //      Using the same structs for input and output is OK in
-       //  BMediaRoster::Connect().
-       err = fRoster->Connect(fAudioOutput.source, fRecInput.destination,
-               &fRecordFormat, &fAudioOutput, &fRecInput);
-       if (err < B_OK) {
-               CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
-                       " failed to connect sound recorder to audio input 
node.\n"));
-               tsobj->Release();
-               fRecordNode->SetHooks(0, 0, 0);
-               return err;
-       }
+       if (!fRecorder->IsConnected()) {
+
+               err = fRecorder->Connect(input, &audioOutput, &fRecordFormat);
+
+               if (err < B_OK) {
+                       CONNECT((stderr, 
"RecorderWindow::MakeRecordConnection():"
+                               " failed to connect sound recorder to audio 
input node.\n"));
 
-       //      Start the time source if it's not running.
-       if ((tsobj->Node() != input) && !tsobj->IsRunning())
-               fRoster->StartNode(tsobj->Node(), BTimeSource::RealTime());
+                       fRecorder->SetHooks(NULL, NULL, NULL);
+                       return err;
+               }
+       }
 
-       tsobj->Release();       //      we're done with this time source 
instance!
        return B_OK;
 }
 
@@ -965,16 +933,13 @@ RecorderWindow::MakeRecordConnection(const media_node & 
input)
 status_t
 RecorderWindow::BreakRecordConnection()
 {
-       status_t err;
+       status_t err = B_OK;
+
+       err = fRecorder->Stop(true);
+       if (err < B_OK)
+               return err;
 
-       //      If we are the last connection, the Node will stop automatically 
since it
-       //      has nowhere to send data to.
-       err = fRoster->StopNode(fRecInput.node, 0);
-       err = fRoster->Disconnect(fAudioOutput.node.node, fAudioOutput.source,
-               fRecInput.node.node, fRecInput.destination);
-       fAudioOutput.source = media_source::null;
-       fRecInput.destination = media_destination::null;
-       return err;
+       return fRecorder->Disconnect();
 }
 
 
@@ -984,8 +949,11 @@ RecorderWindow::StopRecording()
        if (!fRecording)
                return B_OK;
        fRecording = false;
+
        BreakRecordConnection();
-       fRecordNode->SetHooks(NULL,NULL,NULL);
+
+       fRecorder->SetHooks(NULL, NULL, NULL);
+
        if (fRecSize > 0) {
 
                wave_struct header;
@@ -1240,7 +1208,7 @@ RecorderWindow::RemoveCurrentSoundItem() {
 
 void
 RecorderWindow::RecordFile(void* cookie, bigtime_t timestamp,
-       void* data, size_t size, const media_raw_audio_format &format)
+       void* data, size_t size, const media_format &format)
 {
        //      Callback called from the SoundConsumer when receiving buffers.
        RecorderWindow * window = (RecorderWindow *)cookie;
@@ -1249,7 +1217,7 @@ RecorderWindow::RecordFile(void* cookie, bigtime_t 
timestamp,
                //      Write the data to file (we don't buffer or guard file 
access
                //      or anything)
                window->fRecFile.WriteAt(window->fRecSize, data, size);
-               window->fVUView->ComputeLevels(data, size, format.format);
+               window->fVUView->ComputeLevels(data, size, 
format.u.raw_audio.format);
                window->fRecSize += size;
        }
 }
diff --git a/src/apps/soundrecorder/RecorderWindow.h 
b/src/apps/soundrecorder/RecorderWindow.h
index 1688334..d3e3087 100644
--- a/src/apps/soundrecorder/RecorderWindow.h
+++ b/src/apps/soundrecorder/RecorderWindow.h
@@ -21,6 +21,7 @@
 #include <Window.h>
 
 #include "DrawButton.h"
+#include "MediaRecorder.h"
 #include "ScopeView.h"
 #include "SoundListView.h"
 #include "TransportButton.h"
@@ -40,12 +41,8 @@ class BScrollView;
 class BSlider;
 class BStringView;
 
-namespace BPrivate {
-class SoundConsumer;
-}
 
-
-using BPrivate::SoundConsumer;
+using BPrivate::media::BMediaRecorder;
 
 
 class RecorderWindow : public BWindow {
@@ -78,6 +75,7 @@ public:
                };
 
                void AddSoundItem(const BEntry& entry, bool temp = false);
+
                void RemoveCurrentSoundItem();
 
 private:
@@ -95,7 +93,7 @@ private:
                TrackSlider *fTrackSlider;
                UpDownButton * fUpDownButton;
                BMenuField * fInputField;
-               SoundConsumer * fRecordNode;
+               BMediaRecorder * fRecorder;
                BSoundPlayer * fPlayer;
                bool fRecording;
                SoundListView * fSoundList;
@@ -128,8 +126,6 @@ private:
                off_t fRecSize;
 
                media_node fAudioInputNode;
-               media_output fAudioOutput;
-               media_input fRecInput;
 
                BMediaFile *fPlayFile;
                media_format fPlayFormat;
@@ -171,7 +167,7 @@ private:
                status_t UpdatePlayFile(SoundListItem *item, bool updateDisplay 
= false);
                void ErrorAlert(const char * action, status_t err);
 
-static void RecordFile(void * cookie, bigtime_t timestamp, void * data, size_t 
size, const media_raw_audio_format & format);
+static void RecordFile(void * cookie, bigtime_t timestamp, void * data, size_t 
size, const media_format & format);
 static void NotifyRecordFile(void * cookie, int32 code, ...);
 
 static void PlayFile(void * cookie, void * data, size_t size, const 
media_raw_audio_format & format);
diff --git a/src/kits/media/Jamfile b/src/kits/media/Jamfile
index 5f049a1..583b12b 100644
--- a/src/kits/media/Jamfile
+++ b/src/kits/media/Jamfile
@@ -19,7 +19,8 @@ for architectureObject in [ MultiArchSubDirSetup ] {
                SharedLibrary [ MultiArchDefaultGristFiles libmedia.so ] :
                        # Private Media Kit
                        !missing_symbols.cpp
-                       SoundConsumer.cpp
+                       MediaRecorder.cpp
+                       MediaRecorderNode.cpp
 
                        # Public Media Kit
                        Buffer.cpp
diff --git a/src/kits/media/MediaRecorder.cpp b/src/kits/media/MediaRecorder.cpp
new file mode 100644
index 0000000..9c92909
--- /dev/null
+++ b/src/kits/media/MediaRecorder.cpp
@@ -0,0 +1,473 @@
+/*
+ * Copyright 1999, Be Incorporated
+ * Copyright 2014, Dario Casalinuovo
+ * All Rights Reserved.
+ * This file may be used under the terms of the Be Sample Code License.
+ */
+
+
+#include "MediaRecorder.h"
+
+#include <MediaAddOn.h>
+#include <MediaRoster.h>
+#include <TimeSource.h>
+
+#include "MediaDebug.h"
+#include "MediaRecorderNode.h"
+
+
+class MediaNodeReleaser {
+public:
+                               MediaNodeReleaser(media_node& mediaNode,
+                                       bool release = true)
+                                       :
+                                       fNode(mediaNode),
+                                       fRelease(release)
+                               {
+                               }
+
+                               ~MediaNodeReleaser()
+                               {
+                                       if (fRelease)
+                                               
BMediaRoster::Roster()->ReleaseNode(fNode);
+                               }
+
+       void            SetTo(media_node& node)
+                               {
+                                       fNode = node;
+                               }
+
+       void            SetRelease(bool release)
+                               {
+                                       fRelease = release;
+                               }
+
+private:
+       media_node& fNode;
+       bool            fRelease;
+};
+
+
+BMediaRecorder::BMediaRecorder(const char* name, media_type type)
+       :
+       fInitErr(B_OK),
+       fConnected(false),
+       fRunning(false),
+       fTimeSource(NULL),
+       fRecordHook(NULL),
+       fNotifyHook(NULL),
+       fNode(NULL),
+       fBufferCookie(NULL)
+{
+       CALLED();
+
+       BMediaRoster::Roster(&fInitErr);
+
+       if (fInitErr == B_OK) {
+               fNode = new BMediaRecorderNode(name, this, type);
+               fInitErr = BMediaRoster::CurrentRoster()->RegisterNode(fNode);
+       }
+}
+
+
+BMediaRecorder::~BMediaRecorder()
+{
+       CALLED();
+
+       if (fNode != NULL) {
+               Stop();
+               Disconnect();
+               fNode->Release();
+       }
+
+       if (fTimeSource != NULL)
+               fTimeSource->Release();
+
+}
+
+
+status_t
+BMediaRecorder::InitCheck() const
+{
+       CALLED();
+
+       return fInitErr;
+}
+
+
+void
+BMediaRecorder::SetAcceptedFormat(const media_format& format)
+{
+       CALLED();
+
+       fNode->SetAcceptedFormat(format);
+}
+
+
+status_t
+BMediaRecorder::SetHooks(ProcessFunc recordFunc, NotifyFunc notifyFunc,
+       void* cookie)
+{
+       CALLED();
+
+       fRecordHook = recordFunc;
+       fNotifyHook = notifyFunc;
+       fBufferCookie = cookie;
+
+       return B_OK;
+}
+
+
+void
+BMediaRecorder::BufferReceived(void* buffer, size_t size,
+       const media_header& header)
+{
+       CALLED();
+
+       if (fRecordHook) {
+               (*fRecordHook)(fBufferCookie, header.start_time,
+                       buffer, size, Format());
+       }
+}
+
+
+status_t
+BMediaRecorder::Connect(const media_format& format, uint32 flags)
+{
+       CALLED();
+
+       if (fInitErr != B_OK)
+               return fInitErr;
+
+       if (fConnected)
+               return B_MEDIA_ALREADY_CONNECTED;
+
+       return _Connect(&format, flags, NULL, NULL, NULL);
+}
+
+
+status_t
+BMediaRecorder::Connect(const dormant_node_info& dormantInfo,
+       const media_format* format, uint32 flags)
+{
+       CALLED();
+
+       if (fInitErr != B_OK)
+               return fInitErr;
+
+       if (fConnected)
+               return B_MEDIA_ALREADY_CONNECTED;
+
+       return _Connect(format, flags, &dormantInfo, NULL, NULL);
+}
+
+
+status_t
+BMediaRecorder::Connect(const media_node& node,
+       const media_output* useOutput, const media_format* format,
+       uint32 flags)
+{
+       CALLED();
+
+       if (fInitErr != B_OK)
+               return fInitErr;
+
+       if (fConnected)
+               return B_MEDIA_ALREADY_CONNECTED;
+
+       return _Connect(format, flags, NULL, &node, useOutput);
+}
+
+
+status_t
+BMediaRecorder::Disconnect()
+{
+       CALLED();
+
+       status_t err = B_OK;
+
+       if (fInitErr != B_OK)
+               return fInitErr;
+
+       if (!fConnected)
+               return B_MEDIA_NOT_CONNECTED;
+
+       if (!fNode)
+               return B_ERROR;
+
+       if (fRunning)
+               err = Stop();
+
+       if (err != B_OK)
+               return err;
+
+       // do the disconnect
+       err = BMediaRoster::CurrentRoster()->Disconnect(
+               fOutputNode.node, fOutput.source,
+                       fNode->Node().node, fInput.destination);
+
+       BMediaRoster::Roster()->ReleaseNode(fOutputNode);
+
+       if (fTimeSource != NULL) {
+               fTimeSource->Release();
+               fTimeSource = NULL;
+       }
+
+       fConnected = false;
+       fRunning = false;
+
+       return err;
+}
+
+
+status_t
+BMediaRecorder::Start(bool force)
+{
+       CALLED();
+
+       if (fInitErr != B_OK)
+               return fInitErr;
+
+       if (!fConnected)
+               return B_MEDIA_NOT_CONNECTED;
+
+       if (fRunning && !force)
+               return EALREADY;
+
+       if (!fNode)
+               return B_ERROR;
+
+       // start node here
+       status_t err = B_OK;
+
+       if (fNode->Node().kind & B_TIME_SOURCE)
+               err = BMediaRoster::CurrentRoster()->StartTimeSource(
+                       fOutputNode, BTimeSource::RealTime());
+       else
+               err = BMediaRoster::CurrentRoster()->StartNode(
+                       fOutputNode, fTimeSource->Now());
+
+       // then un-mute it
+       if (err == B_OK) {
+               fNode->SetDataEnabled(true);
+               fRunning = true;
+       } else
+               fRunning = false;
+
+       return err;
+}
+
+
+status_t
+BMediaRecorder::Stop(bool force)
+{
+       CALLED();
+
+       if (fInitErr != B_OK)
+               return fInitErr;
+
+       if (!fRunning && !force)
+               return EALREADY;
+
+       if (!fNode)
+               return B_ERROR;
+
+       // should have the Node mute the output here
+       fNode->SetDataEnabled(false);
+
+       fRunning = false;
+
+       return BMediaRoster::CurrentRoster()->StopNode(fNode->Node(), 0);
+}
+
+
+bool
+BMediaRecorder::IsRunning() const
+{
+       CALLED();
+
+       return fRunning;
+}
+
+
+bool
+BMediaRecorder::IsConnected() const
+{
+       CALLED();
+
+       return fConnected;
+}
+
+
+const media_output&
+BMediaRecorder::MediaOutput() const
+{
+       CALLED();
+
+       return fOutput;
+}
+
+
+const media_input&
+BMediaRecorder::MediaInput() const
+{
+       CALLED();
+
+       return fInput;
+}
+
+
+const media_format&
+BMediaRecorder::Format() const
+{
+       CALLED();
+
+       return fOutput.format;
+}
+
+
+status_t
+BMediaRecorder::_Connect(const media_format* format,
+       uint32 flags, const dormant_node_info* dormantNode,
+       const media_node* mediaNode, const media_output* output)
+{
+       CALLED();
+
+       status_t err = B_OK;
+       media_format ourFormat;
+       media_node node;
+       MediaNodeReleaser away(node, false);
+       media_output ourOutput;
+
+       // argument checking and set-up
+       if (format != NULL)
+               ourFormat = *format;
+
+       if (fNode == NULL)
+               return B_ERROR;
+
+       if (mediaNode == NULL && output != NULL)
+               return B_MISMATCHED_VALUES;
+
+       if (dormantNode != NULL && (mediaNode != NULL || output != NULL))
+               return B_MISMATCHED_VALUES;
+
+       if (format == NULL && output != NULL)
+               ourFormat = output->format;
+
+       fNode->SetAcceptedFormat(ourFormat);
+
+       // figure out the node to instantiate
+       if (dormantNode != NULL) {
+
+               err = BMediaRoster::Roster()->InstantiateDormantNode(
+                       *dormantNode, &node, B_FLAVOR_IS_GLOBAL);
+
+               away.SetRelease(true);
+
+       } else if (mediaNode != NULL) {
+               node = *mediaNode;
+       } else {
+               switch (ourFormat.type) {
+
+                       // switch on format for default
+                       case B_MEDIA_RAW_AUDIO:
+                               err = 
BMediaRoster::Roster()->GetAudioInput(&node);
+                               away.SetRelease(true);
+                               break;
+
+                       case B_MEDIA_RAW_VIDEO:
+                       case B_MEDIA_ENCODED_VIDEO:
+                               err = 
BMediaRoster::Roster()->GetVideoInput(&node);
+                               away.SetRelease(true);
+                               break;
+
+                       // give up?
+                       default:
+                               return B_MEDIA_BAD_FORMAT;
+                               break;
+               }
+       }
+
+       fOutputNode = node;
+
+       // figure out the output provided
+
+       if (output != NULL) {
+               ourOutput = *output;
+       } else if (err == B_OK) {
+
+               media_output outputs[10];
+               int32 count = 10;
+
+               err = BMediaRoster::Roster()->GetFreeOutputsFor(node,
+                       outputs, count, &count, ourFormat.type);
+
+               if (err != B_OK)
+                       return err;
+
+               err = B_MEDIA_BAD_SOURCE;
+
+               for (int i = 0; i < count; i++) {
+                       if (format_is_compatible(outputs[i].format, ourFormat)) 
{
+                               ourOutput = outputs[i];
+                               err = B_OK;
+                               ourFormat = outputs[i].format;
+                               break;
+                       }
+
+               }
+
+       } else {
+               return err;
+       }
+
+       if (ourOutput.source == media_source::null)
+               return B_MEDIA_BAD_SOURCE;
+
+       // find our Node's free input
+       media_input ourInput;
+
+       err = fNode->GetInput(&ourInput);
+       if (err != B_OK)
+               return err;
+
+       media_node time_source;
+       if (node.kind & B_TIME_SOURCE)
+               time_source = node;
+       else
+               BMediaRoster::Roster()->GetSystemTimeSource(&time_source);
+
+       // set time source
+       BMediaRoster::Roster()->SetTimeSourceFor(
+               fNode->Node().node, time_source.node);
+
+       fTimeSource = BMediaRoster::CurrentRoster()->MakeTimeSourceFor(
+               fNode->Node());
+
+       if (err != B_OK)
+               return err;
+
+       // start the recorder node (it's always running)
+       err = BMediaRoster::CurrentRoster()->StartNode(
+               fOutputNode, fTimeSource->Now());
+
+       if (err != B_OK)
+               return err;
+
+       // perform the connection
+       fOutput = ourOutput;
+       fInput = ourInput;
+
+       err = BMediaRoster::CurrentRoster()->Connect(fOutput.source,
+               fInput.destination, &ourFormat, &fOutput, &fInput,
+               BMediaRoster::B_CONNECT_MUTED);
+
+       if (err != B_OK)
+               return err;
+
+       fConnected = true;
+       away.SetRelease(false);
+
+       return err;
+}
diff --git a/src/kits/media/MediaRecorderNode.cpp 
b/src/kits/media/MediaRecorderNode.cpp
new file mode 100644
index 0000000..b8c3f97
--- /dev/null
+++ b/src/kits/media/MediaRecorderNode.cpp
@@ -0,0 +1,324 @@
+/*
+ * Copyright 1999, Be Incorporated
+ * Copyright 2014, Dario Casalinuovo
+ * All Rights Reserved.
+ * This file may be used under the terms of the Be Sample Code License.
+ */
+
+
+#include "MediaRecorderNode.h"
+
+#include <Buffer.h>
+#include <scheduler.h>
+#include <TimedEventQueue.h>
+#include <TimeSource.h>
+
+#include "MediaDebug.h"
+#include "MediaRecorder.h"
+
+
+BMediaRecorderNode::BMediaRecorderNode(const char* name,
+       BMediaRecorder* recorder, media_type type)
+       :
+       BMediaNode(name),
+       BMediaEventLooper(),
+       BBufferConsumer(type),
+       fRecorder(recorder)
+{
+       CALLED();
+
+       fInput.destination.id = 1;
+       fInput.destination.port = ControlPort();
+
+       fName.SetTo(name);
+
+       BString str(name);
+       str << " Input";
+       strcpy(fInput.name, str.String());
+}
+
+
+BMediaRecorderNode::~BMediaRecorderNode()
+{
+       CALLED();
+}
+
+
+BMediaAddOn*
+BMediaRecorderNode::AddOn(int32* id) const
+{
+       CALLED();
+
+       if (id)
+               *id = -1;
+
+       return NULL;
+}
+
+
+void
+BMediaRecorderNode::NodeRegistered()
+{
+       CALLED();
+       Run();
+}
+
+
+void
+BMediaRecorderNode::SetRunMode(run_mode mode)
+{
+       CALLED();
+
+       int32 priority;
+
+       if (mode == BMediaNode::B_OFFLINE)
+               priority = B_OFFLINE_PROCESSING;
+       else {
+               switch(ConsumerType()) {
+                       case B_MEDIA_RAW_AUDIO:
+                       case B_MEDIA_ENCODED_AUDIO:
+                               priority = B_AUDIO_RECORDING;
+                               break;
+
+                       case B_MEDIA_RAW_VIDEO:
+                       case B_MEDIA_ENCODED_VIDEO:
+                               priority = B_VIDEO_RECORDING;
+                               break;
+
+                       default:
+                               priority = B_DEFAULT_MEDIA_PRIORITY;
+               }
+       }
+
+       SetPriority(suggest_thread_priority(priority));
+
+       BMediaNode::SetRunMode(mode);
+}
+
+
+void
+BMediaRecorderNode::SetAcceptedFormat(const media_format& format)
+{
+       CALLED();
+
+       fOKFormat = format;
+}
+
+
+status_t
+BMediaRecorderNode::GetInput(media_input* outInput)
+{
+       CALLED();
+
+       fInput.node = Node();
+       *outInput = fInput;
+
+       return B_OK;
+}
+
+
+void
+BMediaRecorderNode::SetDataEnabled(bool enabled)
+{
+       CALLED();
+
+       int32 tag;
+
+       SetOutputEnabled(fInput.source,
+               fInput.destination, enabled, NULL, &tag);
+}
+
+
+void
+BMediaRecorderNode::HandleEvent(const media_timed_event* event,
+       bigtime_t lateness, bool realTimeEvent)
+{
+       CALLED();
+
+       // we ignore them all!
+}
+
+
+void
+BMediaRecorderNode::Start(bigtime_t performanceTime)
+{
+       CALLED();
+
+       if (fRecorder->fNotifyHook)
+               (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+                       B_WILL_START, performanceTime);
+
+       fRecorder->fRunning = true;
+}
+
+
+void
+BMediaRecorderNode::Stop(bigtime_t performanceTime, bool immediate)
+{
+       CALLED();
+
+       if (fRecorder->fNotifyHook)
+               (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+                       B_WILL_STOP, performanceTime, immediate);
+
+       fRecorder->fRunning = false;
+}
+
+
+void
+BMediaRecorderNode::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
+{
+       CALLED();
+
+       if (fRecorder->fNotifyHook)
+               (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+                       B_WILL_SEEK, performanceTime, mediaTime);
+}
+
+
+void
+BMediaRecorderNode::TimeWarp(bigtime_t realTime, bigtime_t performanceTime)
+{
+       CALLED();
+
+       // Since buffers will come pre-time-stamped, we only need to look
+       // at them, so we can ignore the time warp as a consumer.
+       if (fRecorder->fNotifyHook)
+               (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+                       B_WILL_TIMEWARP, realTime, performanceTime);
+}
+
+
+status_t
+BMediaRecorderNode::HandleMessage(int32 message,
+       const void* data, size_t size)
+{
+       CALLED();
+
+       if (BBufferConsumer::HandleMessage(message, data, size) < 0
+               && BMediaEventLooper::HandleMessage(message, data, size) < 0
+               && BMediaNode::HandleMessage(message, data, size) < 0) {
+               HandleBadMessage(message, data, size);
+               return B_ERROR;
+       }
+       return B_OK;
+}
+
+
+status_t
+BMediaRecorderNode::AcceptFormat(const media_destination& dest,
+       media_format* format)
+{
+       CALLED();
+
+       if (format_is_compatible(*format, fOKFormat))
+               return B_OK;
+
+       *format = fOKFormat;
+
+       return B_MEDIA_BAD_FORMAT;
+}
+
+
+status_t
+BMediaRecorderNode::GetNextInput(int32* cookie, media_input* outInput)
+{
+       CALLED();
+
+       if (*cookie == 0) {
+               *cookie = -1;
+               *outInput = fInput;
+               return B_OK;
+       }
+
+       return B_BAD_INDEX;
+}
+
+
+void
+BMediaRecorderNode::DisposeInputCookie(int32 cookie)
+{
+       CALLED();
+}
+
+
+void
+BMediaRecorderNode::BufferReceived(BBuffer* buffer)
+{
+       CALLED();
+
+       fRecorder->BufferReceived(buffer->Data(), buffer->SizeUsed(),
+               *buffer->Header());
+
+       buffer->Recycle();
+}
+
+
+void
+BMediaRecorderNode::ProducerDataStatus(
+       const media_destination& forWhom, int32 status,
+       bigtime_t performanceTime)
+{
+       CALLED();
+}
+
+
+status_t
+BMediaRecorderNode::GetLatencyFor(const media_destination& forWhom,
+       bigtime_t* outLatency, media_node_id* outTimesource)
+{
+       CALLED();
+
+       *outLatency = 0;
+       *outTimesource = TimeSource()->ID();
+
+       return B_OK;
+}
+
+
+status_t
+BMediaRecorderNode::Connected(const media_source &producer,
+       const media_destination &where, const media_format &withFormat,
+       media_input* outInput)
+{
+       CALLED();
+
+       fInput.source = producer;
+       fInput.format = withFormat;
+       *outInput = fInput;
+
+       fRecorder->fConnected = true;
+       fRecorder->fInput = fInput;
+
+       return B_OK;
+}
+
+
+void
+BMediaRecorderNode::Disconnected(const media_source& producer,
+       const media_destination& where)
+{
+       CALLED();
+
+       fInput.source = media_source::null;
+
+       fRecorder->fConnected = false;
+
+       fRecorder->fInput.format = fOKFormat;
+}
+
+
+status_t
+BMediaRecorderNode::FormatChanged(const media_source& producer,
+       const media_destination& consumer, int32 tag,
+       const media_format& format)
+{
+       CALLED();
+
+       if (!format_is_compatible(format, fOKFormat))
+               return B_MEDIA_BAD_FORMAT;
+
+       fInput.format = format;
+
+       return B_OK;
+}
diff --git a/src/kits/media/SoundConsumer.cpp b/src/kits/media/SoundConsumer.cpp
deleted file mode 100644
index e2ca10f..0000000
--- a/src/kits/media/SoundConsumer.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-/******************************************************************************
-/
-/      File:                   SoundConsumer.cpp
-/
-/   Description:       Record sound from some sound-producing Node.
-/
-/      Copyright 1998-1999, Be Incorporated, All Rights Reserved
-/
-******************************************************************************/
-#include "SoundConsumer.h"
-
-#include <new>
-#include <stdio.h>
-
-#include <OS.h>
-#include <scheduler.h>
-#include <Buffer.h>
-#include <TimeSource.h>
-
-#include "AutoDeleter.h"
-
-
-using std::nothrow;
-
-
-namespace BPrivate {
-
-
-//     If we don't mind the format changing to another format while
-//     running, we can define this to 1. Look for the symbol down in the 
source.
-#define ACCEPT_ANY_FORMAT_CHANGE 0
-
-
-//     Compiling with NDEBUG means "release" -- it also turns off assert() and
-//     other such debugging aids. By contrast, DEBUG turns on extra debugging
-//     in some programs.
-#if !NDEBUG
-#define TRACE_SOUNDCONSUMER
-#endif
-
-//     Comment out the FPRINTF part of these lines to reduce verbiage.
-//     Enabling MESSAGE will kill performance on slower machines, because it
-//     prints for each message received (including each buffer).
-#ifdef TRACE_SOUNDCONSUMER
-#define NODE fprintf
-#define MESSAGE fprintf
-#else
-#define NODE(x...)
-#define MESSAGE(x...)
-#endif
-
-
-//     This structure is the body of a request that we use to
-//     implement SetHooks().
-struct set_hooks_q {
-       port_id reply;
-       void * cookie;
-       SoundProcessFunc process;
-       SoundNotifyFunc notify;
-};
-
-
-//     All incoming buffers and Media Kit requests arrive at a
-//     media node in the form of messages (which are generally
-//     dispatched for you by your superclasses' HandleMessage
-//     implementations). Each message has a 'type' which is
-//     analagous to a BMessage's 'what' field. We'll define our
-//     own private message types for our SoundConsumer and
-//     SoundProducer to use. The BeOS reserves a range,
-//     0x60000000 to 0x7fffffff, for us to use.
-enum {
-       MSG_QUIT_NOW = 0x60000000L,
-       MSG_CHANGE_HOOKS
-};
-
-
-SoundConsumer::SoundConsumer(
-       const char * name,
-       SoundProcessFunc recordFunc,
-       SoundNotifyFunc notifyFunc,
-       void * cookie) :
-       BMediaNode(name ? name : "SoundConsumer"),
-       BBufferConsumer(B_MEDIA_RAW_AUDIO)
-{
-       NODE(stderr, "SoundConsumer::SoundConsumer(%p, %p, %p, %p)\n", name,
-               recordFunc, notifyFunc, cookie);
-
-       if (!name) name = "SoundConsumer";
-
-       //      Set up the hook functions.
-       m_recordHook = recordFunc;
-       m_notifyHook = notifyFunc;
-       m_cookie = cookie;
-
-       //      Create the port that we publish as our Control Port.
-       char pname[32];
-       sprintf(pname, "%.20s Control", name);
-       m_port = create_port(10, pname);
-
-       // Initialize our single media_input. Make sure it knows
-       // the Control Port associated with the destination, and
-       // the index of the destination (since we only have one,
-       // that's trivial).
-       m_input.destination.port = m_port;
-       m_input.destination.id = 1;
-       sprintf(m_input.name, "%.20s Input", name);
-
-       // Set up the timing variables that we'll be using.
-       m_trTimeout = 0LL;
-       m_tpSeekAt = 0;
-       m_tmSeekTo = 0;
-       m_delta = 0;
-       m_seeking = false;
-
-       //      Create, and run, the thread that we use to service
-       // the Control Port.
-       sprintf(pname, "%.20s Service", name);
-       m_thread = spawn_thread(ThreadEntry, pname, 110, this);
-       resume_thread(m_thread);
-}
-
-
-SoundConsumer::~SoundConsumer()
-{
-       NODE(stderr, "SoundConsumer::~SoundConsumer()\n");
-       //      Signal to our thread that it's time to go home.
-       write_port(m_port, MSG_QUIT_NOW, 0, 0);
-       status_t s;
-       while (wait_for_thread(m_thread, &s) == B_INTERRUPTED)
-               NODE(stderr, "wait_for_thread() B_INTERRUPTED\n");
-       delete_port(m_port);
-}
-
-
-status_t
-SoundConsumer::SetHooks(SoundProcessFunc recordFunc, SoundNotifyFunc 
notifyFunc,
-       void* cookie)
-{
-       //      SetHooks needs to be synchronized with the service thread, else 
we may
-       //      call the wrong hook function with the wrong cookie, which would 
be bad.
-       //      Rather than do locking, which is expensive, we streamline the 
process
-       //      by sending our service thread a request to change the hooks, 
and waiting
-       //      for the acknowledge.
-       status_t err = B_OK;
-       set_hooks_q cmd;
-       cmd.process = recordFunc;
-       cmd.notify = notifyFunc;
-       cmd.cookie = cookie;
-       //      If we're not in the service thread, we need to round-trip a 
message.
-       if (find_thread(0) != m_thread) {
-               cmd.reply = create_port(1, "SetHooks reply");
-               //      Send the private message to our service thread.
-               err = write_port(ControlPort(), MSG_CHANGE_HOOKS, &cmd, 
sizeof(cmd));
-               if (err >= 0) {
-                       int32 code;
-                       //      Wait for acknowledge from the service thread.
-                       err = read_port_etc(cmd.reply, &code, 0, 0, B_TIMEOUT, 
6000000LL);
-                       if (err > 0) err = 0;
-                       NODE(stderr, "SoundConsumer::SetHooks read reply: %#" 
B_PRIx32
-                               "\n", err);
-               }
-               //      Clean up.
-               delete_port(cmd.reply);
-       } else {
-               //      Within the service thread, it's OK to just go ahead and 
do the
-               //      change.
-               DoHookChange(&cmd);
-       }
-       return err;
-}
-
-
-// #pragma mark -BMediaNode-derived methods
-
-
-port_id
-SoundConsumer::ControlPort() const
-{
-       return m_port;
-}
-
-
-BMediaAddOn*
-SoundConsumer::AddOn(int32 * internal_id) const
-{
-       //      This object is instantiated inside an application.
-       //      Therefore, it has no add-on.
-       if (internal_id) *internal_id = 0;
-       return 0;
-}
-
-
-void
-SoundConsumer::Start(bigtime_t performance_time)
-{
-       //      Since we are a consumer and just blindly accept buffers that are
-       //      thrown at us, we don't need to do anything special in 
Start()/Stop().
-       //      If we were (also) a producer, we'd have to be more elaborate.
-       //      The only thing we do is immediately perform any queued Seek 
based on
-       //      the start time, which is the right thing to do (seeing as we 
were
-       //      Seek()-ed when we weren't started).
-       if (m_seeking) {
-               m_delta = performance_time - m_tmSeekTo;
-               m_seeking = false;
-       }
-       if (m_notifyHook)
-               (*m_notifyHook)(m_cookie, B_WILL_START, performance_time);
-       else
-               Notify(B_WILL_START, performance_time);
-}
-
-
-void
-SoundConsumer::Stop(bigtime_t performance_time, bool immediate)
-{
-       //      Since we are a consumer and just blindly accept buffers that are
-       //      thrown at us, we don't need to do anything special in 
Start()/Stop().
-       //      If we were (also) a producer, we'd have to be more elaborate.
-       //      Note that this is not strictly in conformance with The Rules,
-       //      but since this is not an add-on Node for use with any 
application;
-       //      it's a Node over which we have complete control, we can live 
with
-       //      treating buffers received before the start time or after the 
stop
-       //      time as any other buffer.
-       if (m_notifyHook)
-               (*m_notifyHook)(m_cookie, B_WILL_STOP, performance_time, 
immediate);
-       else
-               Notify(B_WILL_STOP, performance_time, immediate);
-}
-
-
-void
-SoundConsumer::Seek(bigtime_t media_time, bigtime_t performance_time)
-{
-       //      Seek() on a consumer just serves to offset the time stamp
-       //      of received buffers passed to our Record hook function.
-       //      In the hook function, you may wish to save those time stamps
-       //      to disk or otherwise store them. You may also want to
-       //      synchronize this node's media time with an upstream
-       //      producer's media time to make this offset meaningful.
-       if (m_notifyHook)
-               (*m_notifyHook)(m_cookie, B_WILL_SEEK, performance_time, 
media_time);
-       else
-               Notify(B_WILL_SEEK, performance_time, media_time);
-
-       m_tpSeekAt = performance_time;
-       m_tmSeekTo = media_time;
-       m_seeking = true;
-}
-
-
-void
-SoundConsumer::SetRunMode(run_mode mode)
-{
-       if (mode == BMediaNode::B_OFFLINE) {
-               // BMediaNode::B_OFFLINE means we don't need to run in
-               // real time. So, we shouldn't run as a real time
-               // thread.
-               int32 new_prio = suggest_thread_priority(B_OFFLINE_PROCESSING);
-               set_thread_priority(m_thread, new_prio);
-       } else {
-               //      We're running in real time, so we'd better have
-               //      a big enough thread priority to handle it!
-               //      Here's where those magic scheduler values
-               //      come from:
-               //
-               //      * In the worst case, we process one buffer per
-               //        reschedule (we get rescheduled when we go to
-               //        look for a message on our Control Port), so
-               //        in order to keep up with the incoming buffers,
-               //        the duration of one buffer becomes our
-               //        scheduling period. If we don't know anything
-               //        about the buffers, we pick a reasonable
-               //        default.
-               //      * We're a simple consumer, so we don't have to
-               //        be too picky about the jitter. Half a period
-               //        of jitter means that we'd have to get two
-               //        consecutive worst-case reschedules before
-               //        we'd fall behind.
-               //      * The amount of time we spend processing is
-               //        our ProcessingLatency().
-               bigtime_t period = 10000;
-               if (buffer_duration(m_input.format.u.raw_audio) > 0)
-                       period = buffer_duration(m_input.format.u.raw_audio);
-
-               //      assuming we're running for 500 us or less per buffer
-               int32 new_prio = suggest_thread_priority(B_AUDIO_RECORDING,
-                       period, period / 2, ProcessingLatency());
-               set_thread_priority(m_thread, new_prio);
-       }
-}
-
-
-void
-SoundConsumer::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time)
-{
-       //      Since buffers will come pre-time-stamped, we only need to look
-       //      at them, so we can ignore the time warp as a consumer.
-       if (m_notifyHook) {
-               (*m_notifyHook)(m_cookie, B_WILL_TIMEWARP, at_real_time,
-                       to_performance_time);
-       } else
-               Notify(B_WILL_TIMEWARP, at_real_time, to_performance_time);
-}
-
-
-void
-SoundConsumer::Preroll()
-{
-       //      There is nothing for us to do in Preroll()
-}
-
-
-void
-SoundConsumer::SetTimeSource(BTimeSource* /* time_source */)
-{
-       //      We don't need to do anything special to take note of the
-       //      fact that the time source changed, because we get our timing
-       //      information from the buffers we receive.
-}
-
-
-status_t
-SoundConsumer::HandleMessage(int32 message, const void* data, size_t size)
-{
-       // Check with each of our superclasses to see if they
-       // understand the message. If none of them do, call
-       // BMediaNode::HandleBadMessage().
-       if (BBufferConsumer::HandleMessage(message, data, size) < 0
-               && BMediaNode::HandleMessage(message, data, size) < 0) {
-               HandleBadMessage(message, data, size);
-               return B_ERROR;
-       }
-       return B_OK;
-}
-
-
-// #pragma mark - BBufferConsumer-derived methods
-
-
-status_t
-SoundConsumer::AcceptFormat(const media_destination& dest, media_format* 
format)
-{
-       //      We only accept formats aimed at our single input.
-       if (dest != m_input.destination)
-               return B_MEDIA_BAD_DESTINATION;
-
-       if (format->type <= 0) {
-               //      If no format is specified, we say we want raw audio.
-               format->type = B_MEDIA_RAW_AUDIO;
-               format->u.raw_audio = media_raw_audio_format::wildcard;
-       } else if (format->type != B_MEDIA_RAW_AUDIO) {
-               //      If a non-raw-audio format is specified, we tell the 
world what
-               //      we want, and that the specified format was unacceptable 
to us.
-               format->type = B_MEDIA_RAW_AUDIO;
-               format->u.raw_audio = media_raw_audio_format::wildcard;
-               return B_MEDIA_BAD_FORMAT;
-       }
-#if !ACCEPT_ANY_FORMAT_CHANGE
-       //      If we're already connected, and this format doesn't go with the
-       //      format in effect, we dont' accept this new format.
-       if (!format_is_compatible(*format, m_input.format)) {
-               *format = m_input.format;
-               return B_MEDIA_BAD_FORMAT;
-       }
-#endif
-       //      I guess we're OK by now, because we have no particular needs as
-       //      far as frame rate, sample format, etc go.
-       return B_OK;
-}
-
-
-status_t
-SoundConsumer::GetNextInput(int32* cookie, media_input* out_input)
-{
-       NODE(stderr, "SoundConsumer: GetNextInput()\n");
-       //      The "next" is kind of misleading, since it's also used for
-       //      getting the first (and only) input.
-       if (*cookie == 0) {
-               if (m_input.source == media_source::null) {
-                       //      If there's no current connection, make sure we 
return a
-                       //      reasonable format telling the world we accept 
any raw audio.
-                       m_input.format.type = B_MEDIA_RAW_AUDIO;
-                       m_input.format.u.raw_audio = 
media_raw_audio_format::wildcard;
-                       m_input.node = Node();
-                       m_input.destination.port = ControlPort();
-                       m_input.destination.id = 1;
-               }
-               *out_input = m_input;
-               *cookie = 1;
-               return B_OK;
-       }
-       //      There's only one input.
-       return B_BAD_INDEX;
-}
-
-
-void
-SoundConsumer::DisposeInputCookie(int32 /* cookie */)
-{
-       //      We didn't allocate any memory or set any state in GetNextInput()
-       //      so this function is a no-op.
-}
-
-
-void
-SoundConsumer::BufferReceived(BBuffer* buffer)
-{
-       NODE(stderr, "SoundConsumer::BufferReceived()\n");
-       //      Whee, a buffer! Update the seek info, if necessary.
-       if (m_seeking && buffer->Header()->start_time >= m_tpSeekAt) {
-               m_delta = m_tpSeekAt - m_tmSeekTo;
-               m_seeking = false;
-       }
-       //      If there is a record hook, let the interested party have at it!
-       if (m_recordHook) {
-               (*m_recordHook)(m_cookie, buffer->Header()->start_time-m_delta,
-                       buffer->Data(), buffer->Header()->size_used,
-                       m_input.format.u.raw_audio);
-       } else {
-               Record(buffer->Header()->start_time-m_delta, buffer->Data(),
-                       buffer->Header()->size_used, 
m_input.format.u.raw_audio);
-       }
-       //      Buffers should ALWAYS be recycled, else whomever is producing 
them
-       //      will starve.
-       buffer->Recycle();
-}
-
-
-void
-SoundConsumer::ProducerDataStatus(const media_destination& for_whom,
-       int32 status, bigtime_t at_media_time)
-{
-       if (for_whom != m_input.destination)
-               return;
-
-       //      Tell whomever is interested that the upstream producer will or 
won't
-       //      send more data in the immediate future.
-       if (m_notifyHook) {
-               (*m_notifyHook)(m_cookie, B_PRODUCER_DATA_STATUS, status,
-                       at_media_time);
-       } else
-               Notify(B_PRODUCER_DATA_STATUS, status, at_media_time);
-}
-
-
-status_t
-SoundConsumer::GetLatencyFor(const media_destination& for_whom,
-       bigtime_t* out_latency, media_node_id* out_timesource)
-{
-       //      We only accept requests for the one-and-only input of our Node.
-       if (for_whom != m_input.destination)
-               return B_MEDIA_BAD_DESTINATION;
-
-       //      Tell the world about our latency information (overridable by 
user).
-       *out_latency = TotalLatency();
-       *out_timesource = TimeSource()->Node().node;
-       return B_OK;
-}
-
-
-status_t
-SoundConsumer::Connected(const media_source& producer,
-       const media_destination& where, const media_format& with_format,
-       media_input* out_input)
-{
-       NODE(stderr, "SoundConsumer::Connected()\n");
-       //      Only accept connection requests when we're not already 
connected.
-       if (m_input.source != media_source::null)
-               return B_MEDIA_BAD_DESTINATION;
-
-       //      Only accept connection requests on the one-and-only available 
input.
-       if (where != m_input.destination)
-               return B_MEDIA_BAD_DESTINATION;
-
-       //      Other than that, we accept pretty much anything. The format has 
been
-       //      pre-cleared through AcceptFormat(), and we accept any format 
anyway.
-       m_input.source = producer;
-       m_input.format = with_format;
-       //      Tell whomever is interested that there's now a connection.
-       if (m_notifyHook)
-               (*m_notifyHook)(m_cookie, B_CONNECTED, m_input.name);
-       else
-               Notify(B_CONNECTED, m_input.name);
-
-       //      This is the most important line -- return our connection 
information
-       //      to the world so it can use it!
-       *out_input = m_input;
-       return B_OK;
-}
-
-
-void
-SoundConsumer::Disconnected(const media_source& producer,
-       const media_destination& where)
-{
-       //      We can't disconnect something which isn't us.
-       if (where != m_input.destination)
-               return;
-       //      We can't disconnect from someone who isn't connected to us.
-       if (producer != m_input.source)
-               return;
-       //      Tell the interested party that it's time to leave.
-       if (m_notifyHook)
-               (*m_notifyHook)(m_cookie, B_DISCONNECTED);
-       else
-               Notify(B_DISCONNECTED);
-       //      Mark ourselves as not-connected.
-       m_input.source = media_source::null;
-}
-
-
-status_t
-SoundConsumer::FormatChanged(const media_source& producer,
-       const media_destination& consumer, int32 from_change_count,
-       const media_format& format)
-{
-       NODE(stderr, "SoundConsumer::Connected()\n");
-       //      The up-stream guy feels like changing the format. If we can 
accept
-       //      arbitrary format changes, we just say "OK". If, however, we're 
recording
-       //      to a file, that's not such a good idea; we only accept format 
changes
-       //      that are compatible with the format we're already using. You 
set this
-       //      behaviour at compile time by defining ACCEPT_ANY_FORMAT_CHANGE 
to 1 or
-       //      0.
-       status_t err = B_OK;
-#if ACCEPT_ANY_FORMAT_CHANGE
-       media_format fmt(format);
-       err = AcceptFormat(m_input.destination, &fmt);
-#else
-       if (m_input.source != media_source::null) {
-               err = format_is_compatible(format, m_input.format) ? B_OK
-                       : B_MEDIA_BAD_FORMAT;
-       }
-#endif
-       if (err >= B_OK) {
-               m_input.format = format;
-               if (m_notifyHook) {
-                       (*m_notifyHook)(m_cookie, B_FORMAT_CHANGED,
-                               &m_input.format.u.raw_audio);
-               } else
-                       Notify(B_FORMAT_CHANGED, &m_input.format.u.raw_audio);
-       }
-       return err;
-}
-
-
-void
-SoundConsumer::DoHookChange(void* msg)
-{
-       //      Tell the old guy we're changing the hooks ...
-       if (m_notifyHook)
-               (*m_notifyHook)(m_cookie, B_HOOKS_CHANGED);
-       else
-               Notify(B_HOOKS_CHANGED);
-
-       //      ... and then do it.
-       set_hooks_q * ptr = (set_hooks_q *)msg;
-       m_recordHook = ptr->process;
-       m_notifyHook = ptr->notify;
-       m_cookie = ptr->cookie;
-}
-
-
-status_t
-SoundConsumer::ThreadEntry(void* cookie)
-{
-       SoundConsumer* consumer = (SoundConsumer*)cookie;
-       consumer->ServiceThread();
-       return 0;
-}
-
-
-void
-SoundConsumer::ServiceThread()
-{
-       //      The Big Bad ServiceThread receives messages aimed at this
-       //      Node and dispatches them (typically to HandleMessage()).
-       //      If we were a Producer, we might have to do finicky timing and
-       //      queued Start()/Stop() processing in here. But we ain't.
-
-       //      A media kit message will never be bigger than 
B_MEDIA_MESSAGE_SIZE.
-       //      Avoid wasing stack space by dynamically allocating at start.
-       char* msg = new (nothrow) char[B_MEDIA_MESSAGE_SIZE];
-       if (msg == NULL)
-               return;
-       //      Make sure we clean up this data when we exit the function.
-       ArrayDeleter<char> _(msg);
-       int bad = 0;
-       while (true) {
-               //      Call read_port_etc() with a timeout derived from a 
virtual function,
-               //      to allow clients to do special processing if necessary.
-               bigtime_t timeout = Timeout();
-               int32 code = 0;
-               status_t err = read_port_etc(m_port, &code, msg, 
B_MEDIA_MESSAGE_SIZE,
-                       B_TIMEOUT, timeout);
-               MESSAGE(stderr, "SoundConsumer::ServiceThread() port %" B_PRId32
-                       " message %#" B_PRIx32 "\n", m_port, code);
-               //      If we received a message, err will be the size of the 
message
-               //      (including 0).
-               if (err >= B_OK) {
-                       //      Real messages reset the timeout time.
-                       m_trTimeout = 0;
-                       bad = 0;
-                       if (code == MSG_QUIT_NOW) {
-                               //      Check for our private stop message.
-                               if (m_notifyHook)
-                                       (*m_notifyHook)(m_cookie, B_NODE_DIES, 
0);
-                               else
-                                       Notify(B_NODE_DIES, 0);
-                               break;
-                       } else if (code == MSG_CHANGE_HOOKS) {
-                       //      Else check for our private change-hooks message.
-                               DoHookChange(msg);
-                               //      Write acknowledge to waiting thread.
-                               write_port(((set_hooks_q *)msg)->reply, 0, 0, 
0);
-                       } else {
-                               //      Else it has to be a regular media kit 
message;
-                               //      go ahead and dispatch it.
-                               HandleMessage(code, msg, err);
-                       }
-               } else if (err == B_TIMED_OUT) {
-                       //      Timing out means that there was no buffer. Tell 
the interested
-                       //      party.
-                       if (m_notifyHook)
-                               (*m_notifyHook)(m_cookie, B_OP_TIMED_OUT, 
timeout);
-                       else
-                               Notify(B_OP_TIMED_OUT, timeout);
-               } else {
-                       //      Other errors are bad.
-                       MESSAGE(stderr, "SoundConsumer: error %#" B_PRIx32 
"\n", err);
-                       bad++;
-                       //      If we receive three bad reads with no good 
messages inbetween,
-                       //      things are probably not going to improve (like 
the port
-                       //      disappeared or something) so we call it a day.
-                       if (bad > 3) {
-                               if (m_notifyHook)
-                                       (*m_notifyHook)(m_cookie, B_NODE_DIES, 
bad, err, code, msg);
-                               else
-                                       Notify(B_NODE_DIES, bad, err, code, 
msg);
-                               break;
-                       }
-               }
-       }
-}
-
-
-bigtime_t
-SoundConsumer::Timeout()
-{
-       //      Timeout() is called for each call to read_port_etc() in the 
service
-       //      thread to figure out a reasonable time-out value. The default 
behaviour
-       //      we've picked is to exponentially back off from one second and 
upwards.
-       //      While it's true that 44 back-offs will run us out of precision 
in a
-       //      bigtime_t, the time to actually reach 44 consecutive back-offs 
is longer
-       //      than the expected market longevity of just about any piece of 
real
-       //      estate. Is that the sound of an impending year-fifteen-million 
software
-       //      problem? :-)
-       m_trTimeout = (m_trTimeout < 1000000) ? 1000000 : m_trTimeout*2;
-       return m_trTimeout;
-}
-
-
-bigtime_t
-SoundConsumer::ProcessingLatency()
-{
-       //      We're saying it takes us 500 us to process each buffer. If all 
we do is
-       //      copy the data, it probably takes much less than that, but it 
doesn't
-       //      hurt to be slightly conservative.
-       return 500LL;
-}
-
-
-bigtime_t
-SoundConsumer::TotalLatency()
-{
-       //      Had we been a producer that passes buffers on, we'd have to
-       //      include downstream latency in this value. But we are not.
-       return ProcessingLatency();
-}
-
-
-// #pragma mark -
-
-
-void
-SoundConsumer::Record(bigtime_t /*time*/, const void* /*data*/,
-       size_t /*size*/, const media_raw_audio_format& /*format*/)
-{
-       //      If there is no record hook installed, we instead call this 
function
-       //      for received buffers.
-}
-
-
-void
-SoundConsumer::Notify(int32 /*cause*/, ...)
-{
-       //      If there is no notification hook installed, we instead call this
-       //      function for giving notification of various events.
-}
-
-}

############################################################################

Revision:    hrev48668
Commit:      683cf2ff58b85b9224cd8a7e08310c2b1041b952
URL:         http://cgit.haiku-os.org/haiku/commit/?id=683cf2f
Author:      Hamish Morrison <hamishm53@xxxxxxxxx>
Date:        Fri Jan  9 20:56:32 2015 UTC

BMediaRecorder: fix a few issues, fix style, remove unused SoundUtils

* Use the preferred time source (GetTimeSource) for the node
* Fix node releasing when creating the connection fails
* Add virtual slots and padding
* Refactor _Connect method

----------------------------------------------------------------------------

diff --git a/headers/private/media/MediaRecorder.h 
b/headers/private/media/MediaRecorder.h
index 8b6d54e..417be03 100644
--- a/headers/private/media/MediaRecorder.h
+++ b/headers/private/media/MediaRecorder.h
@@ -6,17 +6,32 @@
 #define _MEDIA_RECORDER_H
 
 
+#include <MediaDefs.h>
 #include <MediaNode.h>
-#include <TimeSource.h>
-
-#include "MediaRecorderNode.h"
-#include "SoundUtils.h"
 
 
 namespace BPrivate { namespace media {
 
+
+class BMediaRecorderNode;
+
 class BMediaRecorder {
 public:
+       enum notification {
+               B_WILL_START = 1,       // performance_time
+               B_WILL_STOP,            // performance_time immediate
+               B_WILL_SEEK,            // performance_time media_time
+               B_WILL_TIMEWARP,        // real_time performance_time
+       };
+
+       typedef void                            (*ProcessFunc)(void* cookie,
+                                                                       
bigtime_t timestamp, void* data,
+                                                                       size_t 
size, const media_format& format);
+
+       typedef void                            (*NotifyFunc)(void* cookie,
+                                                                       
notification what, ...);
+
+public:
                                                                
BMediaRecorder(const char* name,
                                                                        
media_type type
                                                                                
= B_MEDIA_UNKNOWN_TYPE);
@@ -25,14 +40,6 @@ public:
 
                        status_t                        InitCheck() const;
 
-       typedef void                            (*ProcessFunc)(void* cookie,
-                                                                       
bigtime_t timestamp, void* data,
-                                                                       size_t 
datasize,
-                                                                       const 
media_format& format);
-
-       typedef void                            (*NotifyFunc)(void* cookie,
-                                                                       int32 
code, ...);
-
                        status_t                        SetHooks(ProcessFunc 
recordFunc = NULL,
                                                                        
NotifyFunc notifyFunc = NULL,
                                                                        void* 
cookie = NULL);
@@ -43,17 +50,14 @@ public:
        virtual status_t                        Start(bool force = false);
        virtual status_t                        Stop(bool force = false);
 
-       virtual status_t                        Connect(const media_format& 
format,
-                                                                       uint32 
flags = 0);
+       virtual status_t                        Connect(const media_format& 
format);
 
        virtual status_t                        Connect(const 
dormant_node_info& dormantInfo,
-                                                                       const 
media_format* format = NULL,
-                                                                       uint32 
flags = 0);
+                                                                       const 
media_format& format);
 
        virtual status_t                        Connect(const media_node& node,
-                                                                       const 
media_output* useOutput = NULL,
-                                                                       const 
media_format* format = NULL,
-                                                                       uint32 
flags = 0);
+                                                                       const 
media_output* output = NULL,
+                                                                       const 
media_format* format = NULL);
 
        virtual status_t                        Disconnect();
 
@@ -67,37 +71,42 @@ public:
 
 protected:
 
-       virtual void                            BufferReceived(void* buffer,
-                                                                       size_t 
size,
+       virtual void                            BufferReceived(void* buffer, 
size_t size,
                                                                        const 
media_header& header);
 private:
 
-               status_t                                _Connect(
-                                                                       const 
media_format* format,
-                                                                       uint32 
flags,
-                                                                       const 
dormant_node_info* dormantNode,
-                                                                       const 
media_node* mediaNode,
-                                                                       const 
media_output* output);
+                       status_t                        _Connect(const 
media_node& mediaNode,
+                                                                       const 
media_output* output,
+                                                                       const 
media_format& format);
 
-               status_t                                fInitErr;
+       virtual void                            _ReservedMediaRecorder0();
+       virtual void                            _ReservedMediaRecorder1();
+       virtual void                            _ReservedMediaRecorder2();
+       virtual void                            _ReservedMediaRecorder3();
+       virtual void                            _ReservedMediaRecorder4();
+       virtual void                            _ReservedMediaRecorder5();
+       virtual void                            _ReservedMediaRecorder6();
+       virtual void                            _ReservedMediaRecorder7();
 
-               bool                                    fConnected;
-               bool                                    fRunning;
+                       status_t                        fInitErr;
 
-               BTimeSource*                    fTimeSource;
+                       bool                            fConnected;
+                       bool                            fRunning;
+                       bool                            fReleaseOutputNode;
 
-               ProcessFunc                             fRecordHook;
-               NotifyFunc                              fNotifyHook;
+                       ProcessFunc                     fRecordHook;
+                       NotifyFunc                      fNotifyHook;
 
-               media_node                              fOutputNode;
-               media_output                    fOutput;
+                       media_node                      fOutputNode;
+                       media_output            fOutput;
 
-               BMediaRecorderNode*             fNode;
-               media_input                             fInput;
+                       BMediaRecorderNode*     fNode;
+                       media_input                     fInput;
 
-               void*                                   fBufferCookie;
+                       void*                           fBufferCookie;
+                       uint32                          fPadding[32];
 
-               friend class                    BMediaRecorderNode;
+                       friend class            BMediaRecorderNode;
 };
 
 }
diff --git a/headers/private/media/MediaRecorderNode.h 
b/headers/private/media/MediaRecorderNode.h
index b1e421e..8a4f2fe 100644
--- a/headers/private/media/MediaRecorderNode.h
+++ b/headers/private/media/MediaRecorderNode.h
@@ -1,6 +1,6 @@
 /*
- * Copyright 1999, Be Incorporated
  * Copyright 2014, Dario Casalinuovo
+ * Copyright 1999, Be Incorporated
  * All Rights Reserved.
  * This file may be used under the terms of the Be Sample Code License.
  */
@@ -76,27 +76,23 @@ protected:
        virtual void                    BufferReceived(BBuffer* buffer);
 
        virtual void                    ProducerDataStatus(
-                                                               const 
media_destination& forWhom,
+                                                               const 
media_destination& destination,
                                                                int32 status,
                                                                bigtime_t 
performanceTime);
 
-       virtual status_t                GetLatencyFor(
-                                                               const 
media_destination& forWhom,
-                                                               bigtime_t*  
outLatency,
-                                                               media_node_id*  
outTimesource);
+       virtual status_t                GetLatencyFor(const media_destination& 
destination,
+                                                               bigtime_t* 
outLatency,
+                                                               media_node_id* 
outTimesource);
 
-       virtual status_t                Connected(
-                                                               const 
media_source& producer,
+       virtual status_t                Connected(const media_source& producer,
                                                                const 
media_destination& where,
-                                                               const 
media_format& withFormat,
+                                                               const 
media_format& format,
                                                                media_input* 
outInput);
 
-       virtual void                    Disconnected(
-                                                               const 
media_source& producer,
+       virtual void                    Disconnected(const media_source& 
producer,
                                                                const 
media_destination& where);
 
-       virtual status_t                FormatChanged(
-                                                               const 
media_source& producer,
+       virtual status_t                FormatChanged(const media_source& 
producer,
                                                                const 
media_destination& consumer,
                                                                int32 tag,
                                                                const 
media_format& format);
diff --git a/headers/private/media/SoundUtils.h 
b/headers/private/media/SoundUtils.h
deleted file mode 100644
index c9e5ec8..0000000
--- a/headers/private/media/SoundUtils.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
-/
-/      File:                   SoundUtils.h
-/
-/   Description:       Utility functions for handling audio data.
-/
-/      Copyright 1998-1999, Be Incorporated, All Rights Reserved
-/
-*******************************************************************************/
-
-#if ! defined( _SoundUtils_h )
-#define _SoundUtils_h
-
-#include <MediaDefs.h>

[ *** diff truncated: 674 lines dropped *** ]



Other related posts: