along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
#include <glibmm/thread.h>
-#include <pbd/error.h>
-#include <pbd/pthread_utils.h>
+#include "pbd/error.h"
+#include "pbd/pthread_utils.h"
+#include "pbd/stacktrace.h"
-#include <ardour/configuration.h>
-#include <ardour/audioengine.h>
-#include <ardour/session.h>
-#include <ardour/audio_diskstream.h>
-#include <ardour/crossfade.h>
-#include <ardour/timestamps.h>
+#include "ardour/audio_diskstream.h"
+#include "ardour/audioengine.h"
+#include "ardour/configuration.h"
+#include "ardour/crossfade.h"
+#include "ardour/io.h"
+#include "ardour/midi_diskstream.h"
+#include "ardour/session.h"
+#include "ardour/timestamps.h"
#include "i18n.h"
Session::start_butler_thread ()
{
/* size is in Samples, not bytes */
-
- dstream_buffer_size = (uint32_t) floor (Config->get_track_buffer_seconds() * (float) frame_rate());
-
- Crossfade::set_buffer_size (dstream_buffer_size);
+ audio_dstream_buffer_size = (uint32_t) floor (Config->get_audio_track_buffer_seconds() * (float) frame_rate());
+
+ /* size is in bytes
+ * XXX: Jack needs to tell us the MIDI buffer size
+ * (i.e. how many MIDI bytes we might see in a cycle)
+ */
+ midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * (float)frame_rate());
+ MidiDiskstream::set_readahead_frames ((nframes_t) (Config->get_midi_readahead() * (float) frame_rate()));
+
+ Crossfade::set_buffer_size (audio_dstream_buffer_size);
butler_should_run = false;
void
Session::terminate_butler_thread ()
{
- void* status;
- char c = ButlerRequest::Quit;
- ::write (butler_request_pipe[1], &c, 1);
- pthread_join (butler_thread, &status);
+ if (butler_thread) {
+ void* status;
+ char c = ButlerRequest::Quit;
+ ::write (butler_request_pipe[1], &c, 1);
+ pthread_join (butler_thread, &status);
+ }
}
void
{
char c = ButlerRequest::Run;
::write (butler_request_pipe[1], &c, 1);
+ // PBD::stacktrace (cerr);
}
void
void *
Session::_butler_thread_work (void* arg)
{
- PBD::ThreadCreated (pthread_self(), X_("Butler"));
+ PBD::notify_gui_about_thread_creation (pthread_self(), X_("Butler"));
return ((Session *) arg)->butler_thread_work ();
return 0;
}
uint32_t err = 0;
int32_t bytes;
bool compute_io;
- struct timeval begin, end;
+ microseconds_t begin, end;
+
struct pollfd pfd[1];
bool disk_work_outstanding = false;
DiskstreamList::iterator i;
}
}
- //for (i = diskstreams.begin(); i != diskstreams.end(); ++i) {
- // cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
- //}
-
if (transport_work_requested()) {
butler_transport_work ();
}
bytes = 0;
compute_io = true;
- gettimeofday (&begin, 0);
+ begin = get_microseconds();
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader ();
-
+
+// for (i = dsl->begin(); i != dsl->end(); ++i) {
+// cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
+// }
+
for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
boost::shared_ptr<Diskstream> ds = *i;
+ /* don't read inactive tracks */
+
+ boost::shared_ptr<IO> io = ds->io();
+
+ if (io && !io->active()) {
+ continue;
+ }
+
switch (ds->do_refill ()) {
case 0:
bytes += ds->read_data_count();
}
if (compute_io) {
- gettimeofday (&end, 0);
-
- double b = begin.tv_sec + (begin.tv_usec/1000000.0);
- double e = end.tv_sec + (end.tv_usec / 1000000.0);
-
- _read_data_rate = bytes / (e - b);
+ end = get_microseconds();
+ if(end-begin > 0) {
+ _read_data_rate = (float) bytes / (float) (end - begin);
+ } else { _read_data_rate = 0; // infinity better
+ }
}
bytes = 0;
compute_io = true;
- gettimeofday (&begin, 0);
+ begin = get_microseconds();
for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
// cerr << "write behind for " << (*i)->name () << endl;
+
+ /* note that we still try to flush diskstreams attached to inactive routes
+ */
- switch ((*i)->do_flush (Session::ButlerContext)) {
+ switch ((*i)->do_flush (ButlerContext)) {
case 0:
bytes += (*i)->write_data_count();
break;
}
if (compute_io) {
- gettimeofday (&end, 0);
-
- double b = begin.tv_sec + (begin.tv_usec/1000000.0);
- double e = end.tv_sec + (end.tv_usec / 1000000.0);
-
- _write_data_rate = bytes / (e - b);
+ // there are no apparent users for this calculation?
+ end = get_microseconds();
+ if(end-begin > 0) {
+ _write_data_rate = (float) bytes / (float) (end - begin);
+ } else {
+ _write_data_rate = 0; // Well, infinity would be better
+ }
}
if (!disk_work_outstanding) {
/* disk i/o in excess of 10000MB/sec indicate the buffer cache
in action. ignore it.
*/
- return _read_data_rate > 10485760000.0f ? 0.0f : _read_data_rate;
+ return _read_data_rate > 10485.7600000f ? 0.0f : _read_data_rate;
}
float
/* disk i/o in excess of 10000MB/sec indicate the buffer cache
in action. ignore it.
*/
- return _write_data_rate > 10485760000.0f ? 0.0f : _write_data_rate;
+ return _write_data_rate > 10485.7600000f ? 0.0f : _write_data_rate;
}
uint32_t