diff --git a/headers/private/media/MediaRecorder.h b/headers/private/media/MediaRecorder.h
new file mode 100644
index 0000000..b6d86b0
--- /dev/null
+++ b/headers/private/media/MediaRecorder.h
@@ -0,0 +1,122 @@
+/*
+ * 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"
+
+typedef void (*ProcessFunc)(void* cookie,
+	bigtime_t timestamp, void* data, size_t datasize,
+	const media_format& format);
+
+typedef void (*NotifyFunc)(void* cookie,
+	int32 code, ...);
+
+
+namespace BPrivate { namespace media {
+
+class BMediaRecorder
+{
+public:
+								BMediaRecorder(const char* name,
+									int32 threadPriority = 0,
+									media_type type
+										= B_MEDIA_UNKNOWN_TYPE);
+
+	virtual						~BMediaRecorder();
+
+			status_t			InitCheck() const;
+
+			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 = 0,
+										uint32 flags = 0);
+
+	virtual status_t			Connect(const media_node& node,
+										const media_output* useOutput = 0,
+										const media_format* format = 0,
+										uint32 flags = 0);
+
+	virtual status_t			Disconnect();
+
+			bool				IsConnected() const;
+			bool				IsRunning() const;
+
+			const media_format&	Format() const;
+
+			const media_node&	Node() const;
+
+			const media_output&	MediaOutput() const;
+			const media_input&	MediaInput() const;
+
+protected:
+
+	virtual	void				BufferReceived(void* buffer,
+									size_t size,
+									const media_header& header);
+
+								BMediaRecorder();
+
+								BMediaRecorder(const BMediaRecorder&
+									recorder);
+
+								BMediaRecorder&  operator=(
+									const BMediaRecorder& );
+
+private:
+
+		status_t				giga_connect(
+									const media_format* format,
+									uint32 flags,
+									const dormant_node_info* dormantNode,
+									const media_node* node,
+									const media_output* output);
+
+		status_t				fInitErr;
+
+		bool					fConnected;
+		bool					fRunning;
+
+		BMediaRecorderNode*		fNode;
+		BTimeSource*			fTimeSource;
+
+		ProcessFunc				fRecordHook;
+		NotifyFunc				fNotifyHook;
+
+		media_node				fOutputNode;
+		media_output			fOutput;
+	
+		media_node				fInputNode;
+		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..0e8a48b
--- /dev/null
+++ b/headers/private/media/MediaRecorderNode.h
@@ -0,0 +1,117 @@
+//	MediaRecorderNode.h
+//	-------------------
+//	Copyright 1999, Be Incorporated.   All Rights Reserved.
+//	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*  rec,
+									int32 priority,
+									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* out_input);
+
+			void			SetDataEnabled(bool enabled);
+
+protected:
+
+	virtual	BMediaAddOn*	AddOn(int32*  internal_id) const;
+
+	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 atRealTime,
+								bigtime_t to_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* out_input);
+	virtual	void			DisposeInputCookie(
+									int32 cookie);
+	virtual	void			BufferReceived(
+									BBuffer* buffer);
+	virtual	void			ProducerDataStatus(
+									const media_destination& for_whom,
+									int32 status,
+									bigtime_t at_performance_time);
+	virtual	status_t		GetLatencyFor(
+									const media_destination& for_whom,
+									bigtime_t*  out_latency,
+									media_node_id*  out_timesource);
+
+	virtual	status_t		Connected(
+									const media_source& producer,
+									const media_destination& where,
+									const media_format& with_format,
+									media_input* out_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 change_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/src/apps/soundrecorder/RecorderWindow.cpp b/src/apps/soundrecorder/RecorderWindow.cpp
index 91f9ea4..1c4167e 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,14 @@ 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 disconnected and deleted
+	delete fRecorder;
+
 	delete fPlayer;
 
 	if (fPlayTrack && fPlayFile)
 		fPlayFile->ReleaseTrack(fPlayTrack);
+
 	if (fPlayFile)
 		delete fPlayFile;
 	fPlayTrack = NULL;
@@ -232,17 +233,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_REAL_TIME_PRIORITY, 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 +460,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 +521,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 +703,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();
 }
 
 
@@ -849,7 +849,7 @@ RecorderWindow::Input(BMessage * message)
 
 
 void
-RecorderWindow::Selected(BMessage * message)
+RecorderWindow::Selected(BMessage* message)
 {
 	//	User selected a sound in list view
 	int32 selIdx = fSoundList->CurrentSelection();
@@ -867,97 +867,68 @@ RecorderWindow::Selected(BMessage * message)
 
 
 status_t
-RecorderWindow::MakeRecordConnection(const media_node & input)
+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()) {
 
-	//	Start the time source if it's not running.
-	if ((tsobj->Node() != input) && !tsobj->IsRunning())
-		fRoster->StartNode(tsobj->Node(), BTimeSource::RealTime());
+		err = fRecorder->Connect(input, &audioOutput, &fRecordFormat);
+
+		if (err < B_OK) {
+			CONNECT((stderr, "RecorderWindow::MakeRecordConnection():"
+				" failed to connect sound recorder to audio input node.\n"));
+
+			fRecorder->SetHooks(NULL, NULL, NULL);
+			return err;
+		}
+	} else {
+		fRecordFormat = fRecorder->Format();
+	}
 
-	tsobj->Release();	//	we're done with this time source instance!
 	return B_OK;
 }
 
@@ -965,15 +936,14 @@ 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;
+
+	err = fRecorder->Disconnect();
 
-	//	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;
 }
 
@@ -984,8 +954,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 +1213,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 +1222,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..b92acd6 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,23 +41,20 @@ class BScrollView;
 class BSlider;
 class BStringView;
 
-namespace BPrivate {
-class SoundConsumer;
-}
 
+using BPrivate::media::BMediaRecorder;
 
-using BPrivate::SoundConsumer;
 
-
-class RecorderWindow : public BWindow {
+class RecorderWindow : public BWindow
+{
 public:
-		RecorderWindow();
-	virtual	~RecorderWindow();
-		status_t InitCheck();
+								RecorderWindow();
+	virtual						~RecorderWindow();
+			status_t			InitCheck();
 
 
-	virtual	bool QuitRequested();
-	virtual	void MessageReceived(BMessage * message);
+	virtual	bool				QuitRequested();
+	virtual	void				MessageReceived(BMessage* message);
 
 		enum {
 			RECORD = 'cw00',			//	command messages
@@ -77,8 +75,10 @@ public:
 			POSITION_CHANGED
 		};
 
-		void AddSoundItem(const BEntry& entry, bool temp = false);
-		void RemoveCurrentSoundItem();
+			void				AddSoundItem(const BEntry& entry,
+									bool temp = false);
+
+			void				RemoveCurrentSoundItem();
 
 private:
 		BMediaRoster * fRoster;
@@ -95,7 +95,7 @@ private:
 		TrackSlider *fTrackSlider;
 		UpDownButton * fUpDownButton;
 		BMenuField * fInputField;
-		SoundConsumer * fRecordNode;
+		BMediaRecorder* fRecorder;
 		BSoundPlayer * fPlayer;
 		bool fRecording;
 		SoundListView * fSoundList;
@@ -128,8 +128,6 @@ private:
 		off_t fRecSize;
 
 		media_node fAudioInputNode;
-		media_output fAudioOutput;
-		media_input fRecInput;
 
 		BMediaFile *fPlayFile;
 		media_format fPlayFormat;
@@ -171,7 +169,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 96dd800..bdb642e 100644
--- a/src/kits/media/Jamfile
+++ b/src/kits/media/Jamfile
@@ -19,6 +19,8 @@ for architectureObject in [ MultiArchSubDirSetup ] {
 		SharedLibrary [ MultiArchDefaultGristFiles libmedia.so ] :
 			# Private Media Kit
 			!missing_symbols.cpp
+			MediaRecorder.cpp
+			MediaRecorderNode.cpp
 			SoundConsumer.cpp
 
 			# Public Media Kit
diff --git a/src/kits/media/MediaRecorder.cpp b/src/kits/media/MediaRecorder.cpp
new file mode 100644
index 0000000..7d35f16
--- /dev/null
+++ b/src/kits/media/MediaRecorder.cpp
@@ -0,0 +1,440 @@
+//	MediaRecorder.cpp
+//	-----------------
+//	Copyright 1999, Be Incorporated.   All Rights Reserved.
+//	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 "MediaRecorderNode.h"
+
+
+class StNodeRelease
+{
+public:
+				StNodeRelease(media_node& mediaNode, bool r = true)
+					:
+					node(mediaNode),
+					rel(r)
+					{}
+
+				~StNodeRelease()
+				{
+					if (rel)
+						BMediaRoster::Roster()->ReleaseNode(node);
+				}
+
+	void		SetRelease(bool r)
+				{
+					rel = r;
+				}
+
+private:
+	media_node& node;
+	bool		rel;
+};
+
+
+BMediaRecorder::BMediaRecorder(const char* name, int32 priority,
+	media_type type)
+	:
+	fInitErr(0),
+	fConnected(false),
+	fRunning(false),
+	fNode(0),
+	fTimeSource(0),
+	fRecordHook(NULL),
+	fNotifyHook(NULL),
+	fBufferCookie(0)
+{
+	(void)BMediaRoster::Roster(&fInitErr);
+
+	if (fInitErr == B_OK) {
+
+		if (priority < 5)
+			priority = 115;
+
+		fNode = new BMediaRecorderNode(name, this, priority, type);
+		fInitErr = BMediaRoster::CurrentRoster()->RegisterNode(fNode);
+
+		if (fInitErr == B_OK)
+			fOutputNode = fNode->Node();
+	}
+}
+
+
+BMediaRecorder::~BMediaRecorder()
+{
+	if (fNode != 0) {
+		(void)Stop();
+
+		(void)Disconnect();
+
+		fNode->Release();
+	}
+
+	if (fTimeSource != 0)
+		fTimeSource->Release();
+
+}
+
+
+status_t
+BMediaRecorder::InitCheck() const
+{
+	return fInitErr;
+}
+
+
+void 
+BMediaRecorder::SetAcceptedFormat(const media_format& format)
+{
+	fNode->SetAcceptedFormat(format);
+}
+
+
+status_t
+BMediaRecorder::SetHooks(ProcessFunc recordFunc, NotifyFunc notifyFunc,
+	void* cookie)
+{
+	fRecordHook = recordFunc;
+	fNotifyHook = notifyFunc;
+	fBufferCookie = cookie;
+
+	return B_OK;
+}
+
+
+void 
+BMediaRecorder::BufferReceived(void* data, size_t size,
+	const media_header& header)
+{
+	if (fRecordHook) {
+		(*fRecordHook)(fBufferCookie, header.start_time,
+			data, size, Format());
+	}
+}
+
+
+status_t 
+BMediaRecorder::Connect(const media_format& format, uint32 flags)
+{
+	if (fInitErr != B_OK)
+		return fInitErr;
+
+	if (fConnected)
+		return B_MEDIA_ALREADY_CONNECTED;
+
+	return giga_connect(&format, flags, 0, 0, 0);
+}
+
+
+status_t 
+BMediaRecorder::Connect(const dormant_node_info& info,
+	const media_format* format, uint32 flags)
+{
+	if (fInitErr != B_OK)
+		return fInitErr;
+
+	if (fConnected)
+		return B_MEDIA_ALREADY_CONNECTED;
+
+	return giga_connect(format, flags, &info, 0, 0);
+}
+
+
+status_t 
+BMediaRecorder::Connect(const media_node& node,
+	const media_output* use_output, const media_format* format,
+	uint32 flags)
+{
+	if (fInitErr != B_OK)
+		return fInitErr;
+
+	if (fConnected)
+		return B_MEDIA_ALREADY_CONNECTED;
+
+	return giga_connect(format, flags, 0, &node, use_output);
+}
+
+
+status_t 
+BMediaRecorder::Disconnect()
+{
+	if (fInitErr != B_OK)
+		return fInitErr;
+
+	if (!fConnected)
+		return B_MEDIA_NOT_CONNECTED;
+
+	if (!fNode)
+		return B_ERROR;
+
+	//	do the disconnect
+	status_t err = BMediaRoster::CurrentRoster()->Disconnect(
+		fOutputNode.node, fOutput.source,
+			fOutputNode.node, fInput.destination);
+
+	if (fTimeSource != 0) {
+		fTimeSource->Release();
+		fTimeSource = 0;
+	}
+
+	fConnected = false;
+	fRunning = false;
+
+	return err;
+}
+
+
+status_t 
+BMediaRecorder::Start(bool force)
+{
+	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 (fInputNode.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 = (err == B_OK);
+
+	return err;
+}
+
+
+status_t 
+BMediaRecorder::Stop(bool force)
+{
+	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 B_OK;
+}
+
+
+bool
+BMediaRecorder::IsRunning() const
+{
+	return fRunning;
+}
+
+
+bool
+BMediaRecorder::IsConnected() const
+{
+	return fConnected;
+}
+
+
+const media_node&
+BMediaRecorder::Node() const
+{
+	return fOutputNode;
+}
+
+
+const media_output&
+BMediaRecorder::MediaOutput() const
+{
+	return fOutput;
+}
+
+
+const media_input&
+BMediaRecorder::MediaInput() const
+{
+	return fInput;
+}
+
+
+const media_format& 
+BMediaRecorder::Format() const
+{
+	return fOutput.format;
+}
+
+
+status_t 
+BMediaRecorder::giga_connect(const media_format* in_format,
+	uint32 in_flags, const dormant_node_info* in_dormant,
+	const media_node* in_node, const media_output* in_output)
+{
+	media_format fmt;
+	media_node node;
+	StNodeRelease away(node, false);
+	status_t err = B_OK;
+	media_output out;
+
+	//	argument checking and set-up
+	if (in_format != 0)
+		fmt = *in_format;
+
+	if (fNode == 0)
+		return B_ERROR;
+
+	if (in_node == 0 && in_output != 0)
+		return B_MISMATCHED_VALUES;
+
+	if (in_dormant != 0 && (in_node != 0 || in_output != 0))
+		return B_MISMATCHED_VALUES;
+
+	if (in_format == 0 && in_output != 0)
+		fmt = in_output->format;
+
+	fNode->SetAcceptedFormat(fmt);
+
+	//	figure out the node
+	//	instantiate?
+	if (in_dormant != 0) {
+		err = BMediaRoster::Roster()->InstantiateDormantNode(
+			*in_dormant, &node, B_FLAVOR_IS_GLOBAL);
+
+		away.SetRelease(true);
+
+	} else if (in_node != 0) {
+		// provided?
+		node = *in_node;
+	} else {
+		switch (fmt.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 (in_output != 0) {
+
+		out = *in_output;
+
+	} else if (err == B_OK) {
+
+		media_output outputs[10];
+		int32 count = 10;
+
+		err = BMediaRoster::Roster()->GetFreeOutputsFor(node, outputs, count,
+			&count, fmt.type);
+
+		if (err == B_OK) {
+
+			err = B_MEDIA_BAD_SOURCE;
+
+			for (int i=0; i<count; i++) {
+				if (format_is_compatible(outputs[i].format, fmt)) {
+					out = outputs[i];
+					err = B_OK;
+					fmt = outputs[i].format;
+					break;
+				}
+
+			}
+
+		}
+
+	}
+
+	//	give up?
+	if (err != B_OK) {
+		return err;
+	}
+
+	if (out.source == media_source::null) {
+		return B_MEDIA_BAD_SOURCE;
+	}
+
+	//	find our Node's free input
+	media_input in;
+	err = fNode->GetInput(&in);
+	media_node time_source;
+
+	if (node.kind & B_TIME_SOURCE) {
+		time_source = node;
+	} else {
+		BMediaRoster::Roster()->GetSystemTimeSource(&time_source);
+	}
+
+	//	set time source
+	if (err == B_OK) {
+		BMediaRoster::Roster()->SetTimeSourceFor(
+			fOutputNode.node, time_source.node);
+
+		fTimeSource = BMediaRoster::CurrentRoster()->MakeTimeSourceFor(
+			fOutputNode);
+	}
+
+	//	start the recorder node (it's always running)
+	if (err == B_OK) {
+		err = BMediaRoster::CurrentRoster()->StartNode(
+			fOutputNode, fTimeSource->Now());
+	}
+
+	//	perform the connection
+	if (err == B_OK) {
+		fOutput = out;
+		fInput = in;
+
+		err = BMediaRoster::CurrentRoster()->Connect(fOutput.source,
+			fInput.destination, &fmt, &fOutput, &fInput,
+			BMediaRoster::B_CONNECT_MUTED);
+
+		if (err == B_OK) {
+			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..8db186d
--- /dev/null
+++ b/src/kits/media/MediaRecorderNode.cpp
@@ -0,0 +1,256 @@
+//	MediaRecorderNode.cpp
+//	---------------------
+//	Copyright 1999, Be Incorporated.   All Rights Reserved.
+//	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 <TimedEventQueue.h>
+#include <TimeSource.h>
+
+#include <stdio.h>
+
+#include "MediaRecorder.h"
+
+
+BMediaRecorderNode::BMediaRecorderNode(const char* name,
+	BMediaRecorder* rec, int32 priority, media_type type)
+	:
+	BMediaNode(name),
+	BMediaEventLooper(),
+	BBufferConsumer(type),
+	fRecorder(rec)
+{
+	SetPriority(priority);
+
+	fInput.destination.id = 1;
+	fInput.destination.port = ControlPort();
+
+	sprintf(fInput.name, "%.20s Input", name);
+
+	fName.SetTo(name);
+}
+
+
+BMediaRecorderNode::~BMediaRecorderNode()
+{
+}
+
+
+BMediaAddOn*
+BMediaRecorderNode::AddOn(int32* internal_id) const
+{
+	if (internal_id)
+		*internal_id = -1;
+
+	return NULL;
+}
+
+
+void 
+BMediaRecorderNode::SetAcceptedFormat(const media_format &format)
+{
+	fOKFormat = format;
+}
+
+
+status_t
+BMediaRecorderNode::GetInput(media_input*  out_input)
+{
+	fInput.node = Node();
+	*out_input = fInput;
+
+	return B_OK;
+}
+
+
+void 
+BMediaRecorderNode::SetDataEnabled(bool enabled)
+{
+	int32 tag;
+
+	(void)SetOutputEnabled(fInput.source, 
+		fInput.destination, enabled, 0, &tag);
+}
+
+
+void 
+BMediaRecorderNode::HandleEvent(const media_timed_event* event,
+	bigtime_t lateness, bool realTimeEvent )
+{
+	//	we ignore them all!
+}
+
+
+void
+BMediaRecorderNode::Start(bigtime_t performance_time)
+{
+	if (fRecorder->fNotifyHook) {
+		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+			B_WILL_START, performance_time);
+	}
+
+	fRecorder->fRunning = true;
+}
+
+
+void
+BMediaRecorderNode::Stop(bigtime_t performance_time, bool immediate)
+{
+	if (fRecorder->fNotifyHook) {
+		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+			B_WILL_STOP, performance_time, immediate);
+	}
+
+	fRecorder->fRunning = false;
+}
+
+
+void
+BMediaRecorderNode::Seek(bigtime_t media_time,
+	bigtime_t performance_time)
+{
+	if (fRecorder->fNotifyHook) {
+		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+			B_WILL_SEEK, performance_time, media_time);
+	}
+}
+
+
+void
+BMediaRecorderNode::TimeWarp(bigtime_t real_time,
+	bigtime_t 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 (fRecorder->fNotifyHook) {
+		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
+			B_WILL_TIMEWARP, real_time, performance_time);
+	}
+}
+
+
+status_t 
+BMediaRecorderNode::HandleMessage(int32 message,
+	const void* data, size_t size)
+{
+	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)
+{
+	if (format_is_compatible(*format, fOKFormat))
+		return B_OK;
+
+	*format = fOKFormat;
+
+	return B_MEDIA_BAD_FORMAT;
+}
+
+
+status_t 
+BMediaRecorderNode::GetNextInput(int32* cookie, media_input* out_input)
+{
+	if (*cookie == 0) {
+		*cookie = -1;
+		*out_input = fInput;
+		return B_OK;
+	}
+
+	return B_BAD_INDEX;
+}
+
+
+void 
+BMediaRecorderNode::DisposeInputCookie(int32 cookie)
+{
+}
+
+
+void 
+BMediaRecorderNode::BufferReceived(BBuffer* buffer)
+{
+	fRecorder->BufferReceived(buffer->Data(), buffer->SizeUsed(),
+		*buffer->Header());
+
+	buffer->Recycle();
+}
+
+
+void 
+BMediaRecorderNode::ProducerDataStatus(
+	const media_destination&  for_whom, int32 status,
+	bigtime_t at_performance_time)
+{
+}
+
+
+status_t
+BMediaRecorderNode::GetLatencyFor(const media_destination& for_whom,
+	bigtime_t* out_latency, media_node_id* out_timesource)
+{
+	*out_latency = 0;
+	*out_timesource = TimeSource()->ID();
+
+	return B_OK;
+}
+
+
+status_t 
+BMediaRecorderNode::Connected(const media_source &producer,
+	const media_destination &where, const media_format &with_format,
+	media_input* out_input)
+{
+	fInput.source = producer;
+	fInput.format = with_format;
+	*out_input = fInput;
+
+	fRecorder->fConnected = true;
+	fRecorder->fInput = fInput;
+	fRecorder->fInputNode = fInput.node;
+
+	return B_OK;
+}
+
+
+void 
+BMediaRecorderNode::Disconnected(const media_source& producer,
+	const media_destination& where)
+{
+	fInput.source = media_source::null;
+	sprintf(fInput.name, "%.20s Input", fName.String());
+
+	fRecorder->fConnected = false;
+
+	fRecorder->fOutput.source = media_source::null;
+	fRecorder->fInput.destination = media_destination::null;
+	fRecorder->fInput.format = fOKFormat;
+}
+
+
+status_t 
+BMediaRecorderNode::FormatChanged(const media_source& producer,
+	const media_destination& consumer, int32 change_tag,
+	const media_format& format)
+{
+	if (!format_is_compatible(format, fOKFormat))
+		return B_MEDIA_BAD_FORMAT;
+
+	fInput.format = format;
+
+	return B_OK;
+}
