diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
index 0c00237..df3c5b2 100644
--- a/gtk2_ardour/engine_dialog.cc
+++ b/gtk2_ardour/engine_dialog.cc
@@ -44,7 +44,7 @@ EngineControl::EngineControl ()
 	  periods_spinner (periods_adjustment),
 	  priority_adjustment (60, 10, 90, 1, 10),
 	  priority_spinner (priority_adjustment),
-	  ports_adjustment (128, 8, 1024, 1, 16),
+	  ports_adjustment (128, 8, 8192, 1, 16),
 	  ports_spinner (ports_adjustment),
 	  realtime_button (_("Realtime")),
 	  no_memory_lock_button (_("Do not lock memory")),
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index 261ed4c..da87c4d 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -101,6 +101,7 @@ source.cc
 source_factory.cc
 tempo.cc
 track.cc
+timerfd.cc
 transient_detector.cc
 utils.cc
 version.cc
diff --git a/libs/ardour/ardour/osc.h b/libs/ardour/ardour/osc.h
index d7c2f4b..b65c768 100644
--- a/libs/ardour/ardour/osc.h
+++ b/libs/ardour/ardour/osc.h
@@ -19,6 +19,7 @@
 
 #ifndef ardour_osc_h
 #define ardour_osc_h
+#define OSC_MULTICAST_ADDR ("239.39.1.99")
 
 #include <string>
 
@@ -49,17 +50,38 @@ class OSC : public BasicUI, public sigc::trackable
 
   private:
 	uint32_t _port;
+
 	volatile bool _ok;
 	volatile bool _shutdown;
 	lo_server _osc_server;
-	lo_server _osc_unix_server;
+	lo_server _osc_multicast_server;
+	lo_address _osc_multicast_server_addr;
+	lo_address clients;
 	std::string _osc_unix_socket_path;
 	std::string _osc_url_file;
 	pthread_t _osc_thread;
 	int _request_pipe[2];
+	int _listeners;
+
+	std::map<std::string, lo_address> _retaddr_map;
+
+	//	CommandMap * _cmd_map;
+	
+	typedef std::pair<int, std::string> InstancePair;
+	typedef std::pair<lo_address, std::string> UrlPair;
+	typedef std::list<UrlPair> UrlList;
+	typedef std::map<InstancePair, UrlList > ControlRegistrationMap;
+	typedef std::map<InstancePair, float> LastValueMap;
+
+	// Arbitrarily added
+	int _set;
+	void * _current_value; 
 
 	static void * _osc_receiver(void * arg);
+	static void * _timer_receiver(void * arg);
+
 	void osc_receiver();
+	void timer_receiver();
 	void send(); // This should accept an OSC payload
 
 	bool init_osc_thread ();
@@ -67,8 +89,8 @@ class OSC : public BasicUI, public sigc::trackable
 	void poke_osc_thread ();
 
 	void register_callbacks ();
-
 	void session_going_away ();
+	lo_address find_or_cache_addr(std::string returl);
 
 	// Handlers for "Application Hook" signals
 	void session_loaded( ARDOUR::Session& );
@@ -76,8 +98,27 @@ class OSC : public BasicUI, public sigc::trackable
 	// end "Application Hook" handles
 
 	std::string get_server_url ();
-	std::string get_unix_server_url ();
-
+	std::string get_multicast_server_url ();
+
+	void update_buffer_load ();
+	void update_cpu_load ();
+
+	int every_twenty_seconds();
+	int every_second ();
+	int every_point_one_seconds ();
+	int every_point_zero_one_seconds ();
+	int every_point_zero_zero_one_seconds ();
+
+	sigc::connection second_connection;
+	sigc::connection point_one_second_connection;
+	sigc::connection point_oh_five_second_connection;
+	sigc::connection point_zero_one_second_connection;
+	sigc::connection point_zero_zero_one_second_connection;
+
+	int subscribe(char *path);
+	int unsubscribe(char *path);
+	int broadcast_state(); 
+	int broadcast_track_state();
 	int current_value (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data);
 
 #define PATH_CALLBACK(name) \
@@ -120,6 +161,12 @@ class OSC : public BasicUI, public sigc::trackable
 
 	PATH_CALLBACK1(set_transport_speed,f,);
 	PATH_CALLBACK1(access_action,s,&);
+	PATH_CALLBACK1(subscribe,s,(char*));
+	PATH_CALLBACK1(unsubscribe,s,(char*));
+	//PATH_CALLBACK1(rec_enable_all,i,&);
+	//PATH_CALLBACK1(punch_in,i,&);
+	//PATH_CALLBACK1(punch_out,i,&);
+	//PATH_CALLBACK1(add_marker_named,s,&);
 };
 
 }
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index e5750e8..ea89ab8 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -889,7 +889,7 @@ class Session : public PBD::StatefulDestructible
 	void reset_playback_load_min ();
 	void reset_capture_load_min ();
 	
-	float read_data_rate () const; // in usec
+	float read_data_rate () const;
 	float write_data_rate () const;
 
 	/* ranges */
diff --git a/libs/ardour/ardour/timerfd.h b/libs/ardour/ardour/timerfd.h
new file mode 100644
index 0000000..c61083b
--- /dev/null
+++ b/libs/ardour/ardour/timerfd.h
@@ -0,0 +1,123 @@
+/*
+
+Copyright (C) 2008 David Taht
+
+This program is in the public domain.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+*/
+
+/* Present a timerfd-like interface, even on systems that don't have timerfd 
+   This allows timers to be used in complex things like poll/select/epoll   
+*/
+
+#ifndef timerfd_h
+#define timerfd_h
+
+/**
+	nanosecond timer on a fd class.
+*/
+
+// For now, pure timerfds is supported
+
+#define PURE_TIMERFD 1
+
+class Timerfd
+{
+private:
+  uint64_t start_time;
+  uint64_t end_time;
+  uint64_t pause_time;
+  uint64_t interval;
+  static int timerfd_mode;
+  clock_t timer;
+  int _timer_fd;
+  bool running;
+#ifndef PURE_TIMERFD
+  sigevent evp;
+  timer_t t;
+  int _control_fd;
+  pthread_t timer_thread;
+#endif
+
+public:
+  Timerfd();
+  ~Timerfd();
+
+  uint64_t get_res();       // What the system reports as possible
+  uint64_t get_real_res();  // What it is really capable of
+
+  int get_fd() { return(_timer_fd); }
+
+  bool start();
+  bool stop();
+
+  int clear(); // Clear pending events from the queue
+
+  bool pause();  // Stop the timer from firing, but keep the start time
+  bool resume(); // Resume the timer
+
+  bool enable();
+  bool disable();
+
+  uint64_t set(uint64_t s);
+  uint64_t get();
+  uint64_t get_elapsed();
+  uint64_t get_remaining();
+  int fired();
+
+  //  operator=()
+  //  operator+=()
+  //  operator-=()
+
+  // A common source of errors is to screw up your timebase
+  // So these convienence functions help
+
+  uint64_t set_nanoseconds(uint64_t s) { return(set(s)); }
+  uint64_t set_microseconds(uint64_t s){ return(set(s * 1000L)); }
+  uint64_t set_milliseconds(uint64_t s){ return(set(s * 1000000L)); }
+  uint64_t set_seconds(uint64_t s)     { return(set(s * 1000000000L)); }
+
+  uint64_t set_ns(uint64_t s){ return(set(s)); }
+  uint64_t set_us(uint64_t s){ return(set(s * 1000L)); }
+  uint64_t set_ms(uint64_t s){ return(set(s * 1000000L)); }
+
+  uint64_t get_nanoseconds()  { return(get()); }
+  uint64_t get_microseconds() { return(get() / 1000L); }
+  uint64_t get_milliseconds() { return(get() / 1000000L); }
+  uint64_t get_seconds()      { return(get() / 1000000000L); }
+
+  uint64_t get_ns() { return(get()); }
+  uint64_t get_us() { return(get() / 1000L); }
+  uint64_t get_ms() { return(get() / 1000000L); }
+
+  uint64_t get_remaining_nanoseconds()  { return(get_remaining()); }
+  uint64_t get_remaining_microseconds() { return(get_remaining() / 1000L); }
+  uint64_t get_remaining_milliseconds() { return(get_remaining() / 1000000L); }
+  uint64_t get_remaining_seconds()      { return(get_remaining() / 1000000000L); }
+
+  uint64_t get_remaining_ns()  { return(get_remaining()); }
+  uint64_t get_remaining_us() { return(get_remaining() / 1000L); }
+  uint64_t get_remaining_ms() { return(get_remaining() / 1000000L); }
+
+  uint64_t get_elapsed_nanoseconds()  { return(get_elapsed()); }
+  uint64_t get_elapsed_microseconds() { return(get_elapsed() / 1000L); }
+  uint64_t get_elapsed_milliseconds() { return(get_elapsed() / 1000000L); }
+  uint64_t get_elapsed_seconds()      { return(get_elapsed() / 1000000000L); }
+
+  uint64_t get_elapsed_ns()  { return(get_elapsed()); }
+  uint64_t get_elapsed_us() { return(get_elapsed() / 1000L); }
+  uint64_t get_elapsed_ms() { return(get_elapsed() / 1000000L); }
+
+  uint64_t restart()
+  {
+		uint64_t retval = stop();
+		start();
+		return retval;
+  }
+};
+
+#endif
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 419efe8..6041a0e 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -2461,7 +2461,7 @@ AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_si
 
 	playback_buf = new RingBufferNPT<Sample> (bufsize);
 	capture_buf = new RingBufferNPT<Sample> (bufsize);
-	capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
+	capture_transition_buf = new RingBufferNPT<CaptureTransition> (1024);
 	
 	/* touch the ringbuffer buffers, which will cause
 	   them to be mapped into locked physical RAM if
diff --git a/libs/ardour/osc.cc b/libs/ardour/osc.cc
index 101e4cb..ac8ae44 100644
--- a/libs/ardour/osc.cc
+++ b/libs/ardour/osc.cc
@@ -18,11 +18,14 @@
  */
 
 #include <iostream>
+#include <algorithm>
+#include <cmath>
 #include <fstream>
+#include <sstream>
 #include <cstdio>
 #include <cstdlib>
 #include <cerrno>
-#include <algorithm>
+#include <iomanip>
 
 #include <sys/poll.h>
 #include <unistd.h>
@@ -33,32 +36,86 @@
 #include <pbd/pthread_utils.h>
 
 #include <ardour/osc.h>
-#include <ardour/session.h>
 #include <ardour/route.h>
+#include <ardour/session.h>
+#include <ardour/location.h>
+#include <ardour/dB.h>
 #include <ardour/audio_track.h>
-
+#include <ardour/timerfd.h>
+#include <ardour/panner.h>
+#include <ardour/tempo.h>
 #include "i18n.h"
 
 using namespace ARDOUR;
 using namespace sigc;
 using namespace std;
+using namespace PBD;
+using boost::shared_ptr;
 
 static void error_callback(int num, const char *m, const char *path)
 {
-#ifdef DEBUG
+  // #ifdef DEBUG
 	fprintf(stderr, "liblo server error %d in path %s: %s\n", num, path, m);
-#endif
+	// #endif
 }
 
+/* epoll is better
+ 
+ void mainloop(int queue)
+ {
+   struct epoll_event list[10];
+   int                events;
+   int                i;
+   struct foo         data;
+ 
+   while(1)
+   {
+     events = epoll_wait(queue,list,10,TIMEOUT);
+     if (events < 0)
+       continue;	// error but ignore for now
+     for (i = 0 ; i < events ; i++)
+     {
+       data = list[i].data.ptr;
+       (*data->fn)(&list[i]);	// 
+     }
+   }
+ }
+ */
+ 
+
 OSC::OSC (uint32_t port)
 	: _port(port)
 {
 	_shutdown = false;
 	_osc_server = 0;
-	_osc_unix_server = 0;
+	_osc_multicast_server = 0;
 	_osc_thread = 0;
+	_listeners = 1;
+	clients = lo_address_new( NULL, "2222" );
+
 }
 
+lo_address 
+ OSC::find_or_cache_addr(string returl)
+ {
+ 	lo_address addr = 0;
+ 
+ 	if (returl.empty()) return 0;
+ 	
+ 	if (_retaddr_map.find(returl) == _retaddr_map.end()) {
+ 		addr = lo_address_new_from_url (returl.c_str());
+ 		if (lo_address_errno (addr) < 0) {
+ 			fprintf(stderr, "addr error %d: %s\n", lo_address_errno(addr), lo_address_errstr(addr));
+ 		}
+ 		_retaddr_map[returl] = addr;
+ 	}
+ 	else {
+ 		addr = _retaddr_map[returl];
+ 	}
+ 	
+ 	return addr;
+  }
+
 int
 OSC::start ()
 {
@@ -82,29 +139,32 @@ OSC::start ()
 		continue;
 	}
 	
-#ifdef ARDOUR_OSC_UNIX_SERVER
-	
-	// APPEARS sluggish for now
-	
-	// attempt to create unix socket server too
-	
-	snprintf(tmpstr, sizeof(tmpstr), "/tmp/sooperlooper_XXXXXX");
-	int fd = mkstemp(tmpstr);
-	
-	if (fd >= 0 ) {
-		unlink (tmpstr);
-		close (fd);
-		
-		_osc_unix_server = lo_server_new (tmpstr, error_callback);
-		
-		if (_osc_unix_server) {
-			_osc_unix_socket_path = tmpstr;
-		}
-	}
-#endif
-	
 	cerr << "OSC @ " << get_server_url () << endl;
 
+ 	/*  This opens up ardour on (hopefully) the same port as the 
+	    ptp server
+	    This allows for multiple ardour instances
+	    I fear for what can happen on a network with multiple 
+	    versions of ardour running */
+  
+ 	for (int j=0; j < 20; ++j) {
+ 		snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
+  		
+ 		if ((_osc_multicast_server = lo_server_new_multicast (OSC_MULTICAST_ADDR,tmpstr, error_callback))) {
+ 		  _osc_multicast_server_addr = lo_address_new(OSC_MULTICAST_ADDR, tmpstr);
+ 		  // lo_server_set_ttl(_osc_multicast_server,1);
+ 			break;
+  		}
+#ifdef DEBUG		
+ 		cerr << "can't get osc multicast at port: " << _port << endl;
+#endif
+ 		_port++;
+		continue;
+ 	}
+  
+ 	cerr << "OSC @ " << get_multicast_server_url () << endl;
+
+
 	_osc_url_file = Glib::build_filename (get_user_ardour_path (), "osc_url");
 
 	ofstream urlfile;
@@ -120,7 +180,7 @@ OSC::start ()
 	register_callbacks();
 	
 	// lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
-		
+	_shutdown = false;	
 	if (!init_osc_thread()) {
 		return -1;
 	}
@@ -140,21 +200,20 @@ OSC::stop ()
 
 	lo_server_free (_osc_server);
 	_osc_server = 0;
+
+	lo_server_free (_osc_multicast_server);
+	_osc_multicast_server = 0;
 	
-	if (!_osc_unix_socket_path.empty()) {
-		// unlink it
-		unlink(_osc_unix_socket_path.c_str());
+	if (!  _osc_url_file.empty() ) {
+	  unlink(_osc_url_file.c_str() );
 	}
-	
-   if (!  _osc_url_file.empty() ) {
-      unlink(_osc_url_file.c_str() );
-   }
 	return 0;
 }
 
 OSC::~OSC()
 {
 	stop ();
+	lo_address_free(clients);
 }
 
 void
@@ -164,7 +223,7 @@ OSC::register_callbacks()
 	lo_server serv;
 
 	srvs[0] = _osc_server;
-	srvs[1] = _osc_unix_server;
+	srvs[1] = _osc_multicast_server;
 	
 	for (size_t i = 0; i < 2; ++i) {
 
@@ -196,6 +255,11 @@ OSC::register_callbacks()
 		REGISTER_CALLBACK (serv, "/ardour/rec_enable_toggle", "", rec_enable_toggle);
 		REGISTER_CALLBACK (serv, "/ardour/toggle_all_rec_enables", "", toggle_all_rec_enables);
 
+		// New stuff
+
+		REGISTER_CALLBACK (serv, "/a3/subscribe", "s", subscribe);
+		REGISTER_CALLBACK (serv, "/a3/unsubscribe", "s", unsubscribe);
+
 #if 0
 		REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
 		REGISTER_CALLBACK (serv, "/ardour/set", "", set);
@@ -211,6 +275,67 @@ OSC::register_callbacks()
 	}
 }
 
+void
+OSC::update_cpu_load ()
+{
+	char buf[32];
+	//	snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
+	// cpu_load_label.set_text (buf);
+}
+
+void
+OSC::update_buffer_load ()
+{
+	char buf[64];
+
+	if (session) {
+		snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
+			  session->playback_load(), session->capture_load());
+	  // buffer_load_label.set_text (buf);
+	} else {
+	  // buffer_load_label.set_text ("");
+	}
+}
+
+
+int
+OSC::every_twenty_seconds ()
+{
+  // Ping OSC devices to make sure they are alive
+	return TRUE;
+}
+
+
+int
+OSC::every_second ()
+{
+  //	update_cpu_load ();
+  //	update_buffer_load ();
+  //	update_disk_space ();
+	return TRUE;
+}
+
+int
+OSC::every_point_one_seconds ()
+{
+  broadcast_state(); /* EMIT_SIGNAL */
+  return TRUE;
+}
+
+int
+OSC::every_point_zero_one_seconds ()
+{
+  broadcast_track_state(); /* EMIT_SIGNAL */
+  return TRUE;
+}
+
+int
+OSC::every_point_zero_zero_one_seconds ()
+{
+  return TRUE; // dunno
+}
+
+
 bool
 OSC::init_osc_thread ()
 {
@@ -244,6 +369,15 @@ OSC::init_osc_thread ()
 	return true;
 }
 
+int OSC::subscribe(char *path) {
+// lo_address lo_message_get_source  	(   	lo_message   	 m  	 ) 
+  return 0;
+}
+int OSC::unsubscribe(char *path) {
+// lo_address lo_message_get_source  	(   	lo_message   	 m  	 ) 
+  return 0;
+}
+
 void
 OSC::terminate_osc_thread ()
 {
@@ -282,13 +416,14 @@ OSC::get_server_url()
 }
 
 std::string
-OSC::get_unix_server_url()
+OSC::get_multicast_server_url()
 {
 	string url;
 	char * urlstr;
 
-	if (_osc_unix_server) {
-		urlstr = lo_server_get_url (_osc_unix_server);
+	if (_osc_multicast_server) {
+		// FIXME broken in current liblo svn
+		urlstr = lo_server_get_url (_osc_multicast_server);
 		url = urlstr;
 		free (urlstr);
 	}
@@ -296,6 +431,186 @@ OSC::get_unix_server_url()
 	return url;
 }
 
+int
+OSC::broadcast_track_state() {
+  if(session && _listeners) {
+    // construct a state struct which we use a couple times
+    int x = 0;
+    nframes_t frame;
+    int settings = 0;
+    int id = 0;
+    int channels = 2;
+    float gain = .5;
+    int ntracks = session->ntracks();
+
+    int panners = 0;
+    vector<float> pan(8);
+    vector<float> volume(8);
+    boost::shared_ptr<Session::RouteList> routes = session->get_routes();
+
+    pan[0] = .4;
+    pan[1] = .6;
+    volume[0] = .7;
+    volume[1] = .9;
+
+
+    // name string 
+    // volume
+    // audio channels
+    // gain float
+    // panners
+    /* 
+       Automation state
+
+	ARDOUR::AutoState gain_state = rs.route().gain_automation_state();
+	if ( gain_state == Touch || gain_state == Play )
+	{
+		notify_gain_changed( &rs, false );
+	}
+	
+	ARDOUR::AutoState panner_state = rs.route().panner().automation_state();
+	if ( panner_state == Touch || panner_state == Play )
+	{
+     */
+
+    /* solo, active, muted, recording */
+
+    // convert it to OSC
+    char msg[32];
+    lo_bundle b = lo_bundle_new(LO_TT_IMMEDIATE);
+    vector<lo_message> m(60); // number of tracks
+
+    x = 0;
+    for ( Session::RouteList::iterator i = routes->begin(); i != routes->end(); ++i ) {
+      Panner & panner = (*i)->panner();
+      gain = (*i)->gain();
+      x = (*i)->remote_control_id();
+      //(*i)->record_enabled() << 1 |
+      settings = (*i)->active() | 
+	(*i)->muted() << 2  | (*i)->soloed() << 3; 
+      // FIXME get more settings, channels, pan... 
+      m[x] = lo_message_new();
+      // My python didn't like this format
+      // sprintf(msg,"/a3/%d/trk",x); 
+      if(!(*i)->master()) {
+	  sprintf(msg,"/a3/trk"); // no, needs to be remote control id
+	} else {
+	  sprintf(msg,"/a3/mst"); // no, needs to be remote control id
+	}
+      lo_message_add_int32(m[x],x);
+      lo_message_add_int32(m[x],settings);
+      lo_message_add_float(m[x],gain);
+      lo_message_add_int32(m[x],channels); // perhaps part of the string
+      lo_message_add_int32(m[x],panners); // perhaps part of the string
+      lo_message_add_string(m[x],(*i)->name().c_str());
+      //      for (int j = 0; j < panners; j++) {
+      //  panner().[j]->get_effective_position(pan[j]);
+      //lo_message_add_float(m[x],pan[j]);
+      // }
+      //      for (int j = 0; j < channels; j++) {
+      //	lo_message_add_float(m[x],volume[j]);
+      // }
+      lo_bundle_add_message(b,msg,m[x]); // FIXME track id as part of the message makes sense
+      // x++;
+    }
+
+    //    lo_bundle_add_message(b,"/a3/gs",m[x]);
+    // temporarily just use one address for testing
+    if(_osc_server) {
+      lo_send_bundle_from(clients, _osc_server, b);
+    }
+    if(_osc_multicast_server) {
+      lo_send_bundle_from(_osc_multicast_server_addr,_osc_multicast_server,b);
+    }
+    // Send it to all listeners that are interested
+    //    u = foreach(url) {
+    //  lo_bundle_send(u,b);
+    // }
+    // Clean up the mess
+
+    lo_bundle_free_messages(b);
+  }
+  
+  return 0;
+}
+
+int
+OSC::broadcast_state() {
+    struct global_state {
+      nframes64_t current_frame;
+      float transport_speed;
+      BBT_Time bbt;
+      SMPTE::Time smpte;
+      // bpm
+      Sample master_volume;
+      Sample master_gain;
+      int settings; // make 64 bits?
+  } g;
+  
+
+  if(session && _listeners) {
+    // construct a state struct which we use a couple times
+    int x = 0;
+    nframes_t frame;
+    //if (session->get_play_range ()) {
+    //	session->request_play_range (false);
+    //}
+	
+    g.current_frame = frame = session->transport_frame();
+    session->bbt_time(frame,g.bbt);
+    smpte_time(frame,g.smpte);
+    g.transport_speed = session->transport_speed();
+    g.settings =  
+      Config->get_clicking() << 14 |
+      session->synced_to_jack() << 13    |
+      session->transport_locked() << 12  |
+      session->get_play_loop()==1 << 11     |
+      session->actively_recording() << 10  |
+      session->get_record_enabled() << 9 |
+      session->is_auditioning() << 8     |
+      session->transport_stopped() << 7  |
+      session->soloing() << 5            |
+      Config->get_punch_in() << 1           |
+      Config->get_punch_out();
+      //      session->timemaster << 6           |
+      // session->running() << 4            ; 
+      //      session->muted() << 3              |
+      //      session->soloing() << 2              |
+
+    // convert it to OSC
+    lo_bundle b = lo_bundle_new(LO_TT_IMMEDIATE);
+    lo_message m;
+    m = lo_message_new();
+    lo_message_add_int32(m,frame);
+    // lo_message_add_int64(m[x],g.current_frame); pyosc didn't like 64 bits
+    lo_message_add_int32(m,g.settings);
+    lo_message_add_float(m,g.transport_speed);
+    lo_message_add_int32(m,g.bbt.bars);
+    lo_message_add_int32(m,g.bbt.beats);
+    lo_message_add_int32(m,g.bbt.ticks);
+    lo_message_add_int32(m,g.smpte.hours);
+    lo_message_add_int32(m,g.smpte.minutes);
+    lo_message_add_int32(m,g.smpte.seconds);
+    lo_message_add_int32(m,g.smpte.frames);
+    
+    lo_bundle_add_message(b,"/a3/gs",m);
+    // Send it to all listeners that are interested
+    //    u = foreach(url) {
+    //  lo_bundle_send(u,b);
+    // }
+  
+    if(_osc_server) {
+      lo_send_bundle_from(clients, _osc_server, b);
+    }
+
+    if(_osc_multicast_server) {
+      lo_send_bundle_from(_osc_multicast_server_addr,_osc_multicast_server,b);
+    }
+    lo_bundle_free_messages(b);
+  }
+  return 0;
+}
+
 
 /* server thread */
 
@@ -307,76 +622,148 @@ OSC::_osc_receiver(void * arg)
 	return 0;
 }
 
+/* Just some notes on how the route API works:
+
+	if (route_table[0]) {
+		boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack> (route_table[0]);
+		lights_pending[LightTrackrec]  = at && at->record_enabled();
+		lights_pending[LightTrackmute] = route_get_muted(0); 
+		lights_pending[LightTracksolo] = route_get_soloed(0);
+}
+
+	route_set_gain (0, slider_position_to_gain (gain_fraction));
+
+	float level_l = route_get_peak_input_power (0, 0);
+show.cc:160:	float level_r = route_get_peak_input_power (0, 1);
+route_get_gain
+
+	set_route_table_size (1);
+
+	sigc::signal<void,std::string,void*> gui_changed;
+	sigc::signal<void,void*> SelectedChanged;
+
+	for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
+		g = (*i)->gain();
+		
+uint32_t
+Route::remote_control_id() const
+{
+	return _remote_control_id;
+}
+*/
+
 void
 OSC::osc_receiver()
 {
-	struct pollfd pfd[3];
-	int fds[3];
-	lo_server srvs[3];
+	struct pollfd pfd[16];
+	int fds[16];
+	lo_server srvs[16];
 	int nfds = 0;
+	int osc_start = 0;
 	int timeout = -1;
 	int ret;
+	Timerfd timers[4];
+
+	_listeners = 1; // FIXME THIS IS JUST A TEST
+
+	fds[nfds++] = _request_pipe[0];
 	
-	fds[0] = _request_pipe[0];
-	nfds++;
+	timers[0].set_milliseconds(10);  // Every 10 ms
+	timers[1].set_milliseconds(100); // Every 100 ms
+	timers[2].set_seconds(20); // Every 20 seconds
+	timers[3].set_seconds(60); // end the test
 	
-	if (_osc_server && lo_server_get_socket_fd(_osc_server) >= 0) {
-		fds[nfds] = lo_server_get_socket_fd(_osc_server);
-		srvs[nfds] = _osc_server;
-		nfds++;
+	for(int i = 0; i<4; i++) {
+	  // Yes you have fds before you enable the timer
+	  fds[nfds++] = timers[i].get_fd(); 
+	  timers[i].enable(); 
 	}
 
-	if (_osc_unix_server && lo_server_get_socket_fd(_osc_unix_server) >= 0) {
-		fds[nfds] = lo_server_get_socket_fd(_osc_unix_server);
-		srvs[nfds] = _osc_unix_server;
-		nfds++;
+	osc_start = nfds;
+	if (_osc_server && lo_server_get_socket_fd(_osc_server) >= 0) {
+	  fds[nfds] = lo_server_get_socket_fd(_osc_server);
+	  srvs[nfds] = _osc_server;
+	  nfds++;
 	}
-	
-	
-	while (!_shutdown) {
 
-		for (int i=0; i < nfds; ++i) {
-			pfd[i].fd = fds[i];
-			pfd[i].events = POLLIN|POLLPRI|POLLHUP|POLLERR;
-			pfd[i].revents = 0;
-		}
-		
-	again:
-		//cerr << "poll on " << nfds << " for " << timeout << endl;
-		if ((ret = poll (pfd, nfds, timeout)) < 0) {
-			if (errno == EINTR) {
-				/* gdb at work, perhaps */
-				goto again;
-			}
-			
-			cerr << "OSC thread poll failed: " <<  strerror (errno) << endl;
-			
-			break;
-		}
+	if (_osc_multicast_server && lo_server_get_socket_fd(_osc_multicast_server) >= 0) {
+	  fds[nfds] = lo_server_get_socket_fd(_osc_multicast_server);
+	  srvs[nfds] = _osc_multicast_server;
+	  nfds++;
+	}	
 
-		//cerr << "poll returned " << ret << "  pfd[0].revents = " << pfd[0].revents << "  pfd[1].revents = " << pfd[1].revents << endl;
-		
-		if (_shutdown) {
-			break;
-		}
-		
-		if ((pfd[0].revents & ~POLLIN)) {
-			cerr << "OSC: error polling extra port" << endl;
-			break;
-		}
+	while (!_shutdown) {
+	  for (int i=0; i < nfds; ++i) {
+	    pfd[i].fd = fds[i];
+	    pfd[i].events = POLLIN|POLLPRI|POLLHUP|POLLERR;
+	    pfd[i].revents = 0;
+	  }
+	  
+	again:
+	  //cerr << "poll on " << nfds << " for " << timeout << endl;
+	  if ((ret = poll (pfd, nfds, timeout)) < 0) {
+	    if ( errno == EINTR) {
+	      /* gdb at work, perhaps */
+	      if(!_shutdown) {
+		goto again;
+	      } 
+	    }
+	    
+	    cerr << "OSC thread poll failed: " <<  strerror (errno) << endl;
+	    
+	    break;
+	  }
+
+	  //cerr << "poll returned " << ret << "  pfd[0].revents = " << pfd[0].revents << "  pfd[1].revents = " << pfd[1].revents << endl;
 		
-		for (int i=1; i < nfds; ++i) {
-			if (pfd[i].revents & POLLIN)
-			{
-				// this invokes callbacks
-				//cerr << "invoking recv on " << pfd[i].fd << endl;
-				lo_server_recv(srvs[i]);
-			}
-		}
-
+	  if (_shutdown) {
+	    break;
+	  }
+	  
+	  if ((pfd[0].revents & ~POLLIN)) {
+	    cerr << "OSC: error polling extra port" << endl;
+	    break;
+	  }
+	  
+	  if(pfd[1].revents & POLLIN) {
+	    timers[0].clear();
+	    if(_listeners) {
+	      // std::cout << "Broadcasting Track packet" << std::endl; 
+	      broadcast_track_state();
+	    }
+	  }
+	  
+	  if(pfd[2].revents & POLLIN) {
+	    timers[1].clear();
+	    // std::cout << "Broadcasting Control packet" << std::endl; 
+	    broadcast_state();
+	  }
+	  
+	  if(pfd[3].revents & POLLIN) {
+	    timers[2].clear();
+	    //	    if(_listeners) {
+	      std::cout << "Sending Ping packet" << std::endl;
+	      //	    }
+	  }
+	  
+	  if(pfd[4].revents & POLLIN) {
+	    timers[3].clear();
+	    std::cerr << "Reaping non-pong" << std::endl;
+	  }
+	  
+	   for (int i=osc_start; i < nfds; ++i) {
+	    if (pfd[i].revents & POLLIN)
+	      {
+		// this invokes callbacks
+		//cerr << "invoking recv on " << pfd[i].fd << endl;
+		lo_server_recv(srvs[i]);
+	      }
+	  }
+	  
+	  
 	}
-
-	//cerr << "SL engine shutdown" << endl;
+	
+	cerr << "OSC engine shutdown" << endl;
 	
 	if (_osc_server) {
 		int fd = lo_server_get_socket_fd(_osc_server);
@@ -388,16 +775,19 @@ OSC::osc_receiver()
 		_osc_server = 0;
 	}
 
-	if (_osc_unix_server) {
-		cerr << "freeing unix server" << endl;
-		lo_server_free (_osc_unix_server);
-		_osc_unix_server = 0;
+	if (_osc_multicast_server) {
+		// FIXME shutdown right
+		cerr << "freeing multicast server" << endl;
+		lo_server_free (_osc_multicast_server);
+		_osc_multicast_server = 0;
 	}
 	
 	close(_request_pipe[0]);
 	close(_request_pipe[1]);
 }
 
+/* server thread */
+
 void
 OSC::set_session (Session& s)
 {
@@ -435,50 +825,51 @@ OSC::session_exported( std::string path, std::string name ) {
 int 
 OSC::current_value (const char *path, const char *types, lo_arg **argv, int argc, void *data, void* user_data) 
 { 
-#if 0
-	const char* returl;
+	if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != 's') {
 
-	if (argc < 3 || types == 0 || strlen (types) < 3 || types[0] != 's' || types[1] != 's' || types[2] != s) {
 		return 1;
 	}
 
-	const char *returl = argv[1]->s;
+	const char *messagestr = (const char *) argv[0]->s;
+	const char *returl = (const char *) argv[1]->s;
+
 	lo_address addr = find_or_cache_addr (returl);
 
-	const char *retpath = argv[2]->s;
+	const char *retpath = (const char *) argv[2]->s;
+
 
 	
-	if (strcmp (argv[0]->s, "transport_frame")) {
+	if (strcmp (messagestr, "transport_frame")) {
 
 		if (session) {
 			lo_send (addr, retpath, "i", session->transport_frame());
 		}
 
-	} else if (strcmp (argv[0]->s, "transport_speed")) {
+	} else if (strcmp (messagestr, "transport_speed")) {
 
 		if (session) {
-			lo_send (addr, retpath, "i", session->transport_frame());
+			lo_send (addr, retpath, "f", session->transport_speed());
 		}
 
-	} else if (strcmp (argv[0]->s, "transport_locked")) {
+	} else if (strcmp (messagestr, "transport_locked")) {
 
 		if (session) {
-			lo_send (addr, retpath, "i", session->transport_frame());
+			lo_send (addr, retpath, "i", session->transport_locked());
 		}
 
-	} else if (strcmp (argv[0]->s, "punch_in") {
+	} else if (strcmp (messagestr, "punch_in")) { // FIXME
 
 		if (session) {
 			lo_send (addr, retpath, "i", session->transport_frame());
 		}
 
-	} else if (strcmp (argv[0]->s, "punch_out") {
+	} else if (strcmp (messagestr, "punch_out")) { // FIXME
 
 		if (session) {
 			lo_send (addr, retpath, "i", session->transport_frame());
 		}
 
-	} else if (strcmp (argv[0]->s, "rec_enable") {
+	} else if (strcmp (messagestr, "rec_enable")) { // FIXME
 
 		if (session) {
 			lo_send (addr, retpath, "i", session->transport_frame());
@@ -488,6 +879,5 @@ OSC::current_value (const char *path, const char *types, lo_arg **argv, int argc
 
 		/* error */
 	}
-#endif
 	return 0;
 }
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index b11ed56..43b0753 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -1275,6 +1275,8 @@ void
 Session::enable_record ()
 {
 	/* XXX really atomic compare+swap here */
+        // int new_status = Recording;
+	// g_atomic_int_compare_and_exchange(&_record_status,0,Recording);
 	if (g_atomic_int_get (&_record_status) != Recording) {
 		g_atomic_int_set (&_record_status, Recording);
 		_last_record_location = _transport_frame;
diff --git a/libs/ardour/timerfd.cc b/libs/ardour/timerfd.cc
new file mode 100644
index 0000000..55fc860
--- /dev/null
+++ b/libs/ardour/timerfd.cc
@@ -0,0 +1,388 @@
+// #define _GNU_SOURCE
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+
+#include <iostream>
+#include <boost/cstdint.hpp>
+#include <ardour/timerfd.h>
+
+/*
+ ** This were good at the time of 2.6.23-rc7 ...
+ **/
+
+#ifdef __linux__
+#ifndef __NR_timerfd
+#if defined(__x86_64__)
+#define __NR_timerfd_create 283
+#define __NR_timerfd_settime 286
+#define __NR_timerfd_gettime 287
+#elif defined(__i386__)
+#define __NR_timerfd_create 322
+#define __NR_timerfd_settime 325
+#define __NR_timerfd_gettime 326
+#else
+#error Cannot detect your architecture!
+#endif
+#else
+#warning Using predefined values for timerfd in linux 2.6.24 and later
+#undef __NR_timerfd_create 
+#undef __NR_timerfd_settime 
+#undef __NR_timerfd_gettime 
+
+#if defined(__x86_64__)
+#define __NR_timerfd_create 283
+#define __NR_timerfd_settime 286
+#define __NR_timerfd_gettime 287
+#elif defined(__i386__)
+#define __NR_timerfd_create 322
+#define __NR_timerfd_settime 325
+#define __NR_timerfd_gettime 326
+#endif
+#endif
+#endif
+
+/* Definitions from include/linux/timerfd.h */
+#define TFD_TIMER_ABSTIME (1 << 0)
+
+static int timerfd_create(int clockid, int flags) {
+
+	return syscall(__NR_timerfd_create, clockid, flags);
+}
+
+static int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr,
+		    struct itimerspec *otmr) {
+
+	return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr);
+}
+
+static int timerfd_gettime(int ufc, struct itimerspec *otmr) {
+
+	return syscall(__NR_timerfd_gettime, ufc, otmr);
+}
+
+Timerfd::~Timerfd() {
+  running = false;
+  ::close(_timer_fd);
+}
+
+Timerfd::Timerfd() {
+  running = false;
+  _timer_fd = 0;
+  if(timerfd_mode != 2) {
+    _timer_fd = timerfd_create(CLOCK_MONOTONIC,0);
+    if(_timer_fd < 1) {
+      timerfd_mode = 2;
+    std::cerr << "Can't create timerfd " << errno << std::endl;
+    } else {
+      timerfd_mode = 1;
+    }
+  } else {
+    std::cerr << "Falling back to pthreads" << std::endl;
+  }
+}
+
+// What the system reports as possible
+uint64_t 
+Timerfd::get_res() {
+}
+
+  // What it is really capable of
+uint64_t 
+Timerfd::get_real_res() {
+}
+
+bool Timerfd::start() {
+  bool old = running;
+  running = true; // atomic?
+  enable();
+  return(old);
+}
+ 
+bool 
+Timerfd::stop() {
+  bool old = running;
+  running = false; // atomic
+  disable();
+  return(old);
+}
+
+int 
+Timerfd::clear() {
+  uint64_t t1;
+  read(_timer_fd,&t1,sizeof(t1));
+  // Do a read on the fd
+}
+
+// Stop the timer from firing, but keep the start time
+bool 
+Timerfd::pause() {
+  struct itimerspec now;
+  struct itimerspec then;
+  now.it_interval.tv_sec  = 0;
+  now.it_interval.tv_nsec = 0;
+  timerfd_settime(_timer_fd, 0, &now, &then);
+  // pull the start time
+  // 
+  return(true);
+}
+
+// Resume the timer
+bool 
+Timerfd::resume() {
+  uint64_t s = interval;
+  struct itimerspec now;
+  now.it_interval.tv_sec  = s / 1000000000L;
+  now.it_interval.tv_nsec = s % 1000000000L;
+  timerfd_settime(_timer_fd, 0, &now, NULL);
+  // pull the start time
+  // 
+  return(s);
+}
+
+bool Timerfd::enable() {
+  struct itimerspec now;
+  struct itimerspec then;
+  int ret;
+  now.it_interval.tv_sec  = interval / 1000000000L;
+  now.it_interval.tv_nsec = interval % 1000000000L;
+  now.it_value.tv_sec = now.it_interval.tv_sec;
+  now.it_value.tv_nsec = now.it_interval.tv_nsec;
+
+  ret = timerfd_settime(_timer_fd, 0, &now, &then);
+  // pull the start time
+  // 
+  if(ret != 0) {
+    std::cerr << "enable returned: " << ret << " errno: " << strerror(errno) << std::endl;
+  }
+  return(true);
+}
+
+bool 
+Timerfd::disable() {
+  struct itimerspec now;
+  struct itimerspec then;
+  now.it_interval.tv_sec  = 0;
+  now.it_interval.tv_nsec = 0;
+  timerfd_settime(_timer_fd, 0, &now, &then);
+  // pull the start time
+  // 
+  return(true);
+}
+
+int 
+Timerfd::fired() {
+}
+
+uint64_t 
+Timerfd::set(uint64_t s) {
+  interval = s;
+  return(s);
+}
+
+uint64_t 
+Timerfd::get() {
+  struct itimerspec now;
+  timerfd_gettime(_timer_fd, &now);
+  uint64_t total = (uint64_t) now.it_interval.tv_sec * 1000000000L;
+  return (now.it_interval.tv_nsec + total);
+}
+
+uint64_t 
+Timerfd::get_elapsed() {
+}
+
+uint64_t 
+Timerfd::get_remaining() {
+}
+
+int Timerfd::timerfd_mode = 0;
+
+#ifdef _TIMER_TEST
+
+struct tmr_type {
+	int id;
+	char const *name;
+};
+
+
+static unsigned long long getustime(int clockid) {
+	struct timespec tp;
+
+	if (clock_gettime((clockid_t) clockid, &tp)) {
+		perror("clock_gettime");
+		return 0;
+	}
+
+	return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
+}
+
+static void set_timespec(struct timespec *tmr, unsigned long long ustime) {
+
+	tmr->tv_sec = (time_t) (ustime / 1000000ULL);
+	tmr->tv_nsec = (long) (1000ULL * (ustime % 1000000ULL));
+}
+
+static long waittmr(int tfd, int timeo) {
+	u_int64_t ticks;
+	struct pollfd pfd;
+
+	pfd.fd = tfd;
+	pfd.events = POLLIN;
+	pfd.revents = 0;
+	if (poll(&pfd, 1, timeo) < 0) {
+		perror("poll");
+		return -1;
+	}
+	if ((pfd.revents & POLLIN) == 0) {
+		fprintf(stdout, "no ticks happened\n");
+		return -1;
+	}
+	if (read(tfd, &ticks, sizeof(ticks)) != sizeof(ticks)) {
+		perror("timerfd read");
+		return -1;
+	}
+
+	return ticks;
+}
+
+
+int main(int ac, char **av) {
+	int i, tfd, tfd2;
+	long ticks;
+	unsigned long long tnow, ttmr;
+	u_int64_t uticks;
+	struct itimerspec tmr;
+	struct tmr_type clks[] = {
+		{ CLOCK_MONOTONIC, "CLOCK MONOTONIC" },
+		{ CLOCK_REALTIME, "CLOCK REALTIME" },
+	};
+
+	for (i = 0; i < sizeof(clks) / sizeof(clks[0]); i++) {
+		fprintf(stdout, "\n\n---------------------------------------\n");
+		fprintf(stdout, "| testing %s\n", clks[i].name);
+		fprintf(stdout, "---------------------------------------\n\n");
+
+		fprintf(stdout, "relative timer test (at 500 ms) ...\n");
+		set_timespec(&tmr.it_value, 500 * 1000);
+		set_timespec(&tmr.it_interval, 0);
+		tnow = getustime(clks[i].id);
+		if ((tfd = timerfd_create(clks[i].id, 0)) == -1) {
+			perror("timerfd");
+			return 1;
+		}
+		fprintf(stdout, "timerfd = %d\n", tfd);
+
+		if (timerfd_settime(tfd, 0, &tmr, NULL)) {
+			perror("timerfd_settime");
+			return 1;
+		}
+
+		fprintf(stdout, "waiting timer ...\n");
+		ticks = waittmr(tfd, -1);
+		ttmr = getustime(clks[i].id);
+		if (ticks <= 0)
+			fprintf(stdout, "whooops! no timer showed up!\n");
+		else
+			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+				ticks, (ttmr - tnow) / 1000);
+
+
+		fprintf(stdout, "absolute timer test (at 500 ms) ...\n");
+		tnow = getustime(clks[i].id);
+		set_timespec(&tmr.it_value, tnow + 500 * 1000);
+		set_timespec(&tmr.it_interval, 0);
+		if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
+			perror("timerfd_settime");
+			return 1;
+		}
+
+		fprintf(stdout, "wating timer ...\n");
+		ticks = waittmr(tfd, -1);
+		ttmr = getustime(clks[i].id);
+		if (ticks <= 0)
+			fprintf(stdout, "whooops! no timer showed up!\n");
+		else
+			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+				ticks, (ttmr - tnow) / 1000);
+
+		fprintf(stdout, "sequential timer test (100 ms clock) ...\n");
+		tnow = getustime(clks[i].id);
+		set_timespec(&tmr.it_value, tnow + 100 * 1000);
+		set_timespec(&tmr.it_interval, 100 * 1000);
+		if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
+			perror("timerfd_settime");
+			return 1;
+		}
+
+		fprintf(stdout, "sleeping 1 second ...\n");
+		sleep(1);
+		if (timerfd_gettime(tfd, &tmr)) {
+			perror("timerfd_gettime");
+			return 1;
+		}
+		fprintf(stdout, "timerfd_gettime returned:\n"
+			"\tit_value = { %ld, %ld } it_interval = { %ld, %ld }\n",
+			(long) tmr.it_value.tv_sec, (long) tmr.it_value.tv_nsec,
+			(long) tmr.it_interval.tv_sec, (long) tmr.it_interval.tv_nsec);
+		fprintf(stdout, "sleeping 1 second ...\n");
+		sleep(1);
+
+		fprintf(stdout, "wating timer ...\n");
+		ticks = waittmr(tfd, -1);
+		ttmr = getustime(clks[i].id);
+		if (ticks <= 0)
+			fprintf(stdout, "whooops! no timer showed up!\n");
+		else
+			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+				ticks, (ttmr - tnow) / 1000);
+
+
+		fprintf(stdout, "O_NONBLOCK test ...\n");
+		tnow = getustime(clks[i].id);
+		set_timespec(&tmr.it_value, 100 * 1000);
+		set_timespec(&tmr.it_interval, 0);
+		if (timerfd_settime(tfd, 0, &tmr, NULL)) {
+			perror("timerfd_settime");
+			return 1;
+		}
+		fprintf(stdout, "timerfd = %d\n", tfd);
+
+		fprintf(stdout, "wating timer (flush the single tick) ...\n");
+		ticks = waittmr(tfd, -1);
+		ttmr = getustime(clks[i].id);
+		if (ticks <= 0)
+			fprintf(stdout, "whooops! no timer showed up!\n");
+		else
+			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
+				ticks, (ttmr - tnow) / 1000);
+
+		fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK);
+
+		if (read(tfd, &uticks, sizeof(uticks)) > 0)
+			fprintf(stdout, "whooops! timer ticks not zero when should have been\n");
+		else if (errno != EAGAIN)
+			fprintf(stdout, "whooops! bad errno value (%d = '%s')!\n",
+				errno, strerror(errno));
+		else
+			fprintf(stdout, "success\n");
+
+		fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) & ~O_NONBLOCK);
+
+		close(tfd);
+	}
+
+	return 0;
+}
+
+#endif
diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc
index 7c03252..6f224d0 100644
--- a/libs/surfaces/control_protocol/basic_ui.cc
+++ b/libs/surfaces/control_protocol/basic_ui.cc
@@ -292,3 +292,29 @@ BasicUI::sample_to_smpte (nframes_t sample, SMPTE::Time& smpte, bool use_offset,
 {
 	session->sample_to_smpte (sample, *((SMPTE::Time*)&smpte), use_offset, use_subframes);
 }
+
+
+void 
+BasicUI::rec_enable_all (nframes_t sample, bool enable) const
+{
+
+}
+
+void 
+BasicUI::add_marker_named (nframes_t sample, char *s) 
+{
+
+}
+
+void 
+BasicUI::punch_in (nframes_t sample, bool enable) 
+{
+
+}
+
+void 
+BasicUI::punch_out (nframes_t sample, bool enable)
+{
+
+}
+
diff --git a/libs/surfaces/control_protocol/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/control_protocol/basic_ui.h
index c8b5a2a..44fd3a2 100644
--- a/libs/surfaces/control_protocol/control_protocol/basic_ui.h
+++ b/libs/surfaces/control_protocol/control_protocol/basic_ui.h
@@ -26,6 +26,8 @@
 #include <jack/types.h>
 #include <control_protocol/smpte.h>
 
+typedef unsigned int nframes_t;
+
 namespace ARDOUR {
 	class Session;
 }
@@ -78,9 +80,15 @@ class BasicUI {
 	void smpte_to_sample (SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes) const;
 	void sample_to_smpte (jack_nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes) const;
 
+	void rec_enable_all (nframes_t sample, bool enable) const;
+	void add_marker_named(nframes_t sample, char *s);
+	void punch_in(nframes_t sample, bool i);
+	void punch_out(nframes_t sample, bool i);
+
   protected:
 	BasicUI ();
 	ARDOUR::Session* session;
 };
 
+
 #endif /* __ardour_basic_ui_h__ */
