use libsndfile for all audio file i/o, and rename DiskStream AudioDiskStream

git-svn-id: svn://localhost/ardour2/trunk@589 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2006-06-14 21:17:32 +00:00
parent 2387ef8bfb
commit b09ab54654
79 changed files with 1113 additions and 1495 deletions

View file

@ -2,7 +2,7 @@
export ARDOUR_PATH=./glade:./pixmaps:.
export LD_LIBRARY_PATH=../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd3:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libglademm:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd3:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libsndfile:$LD_LIBRARY_PATH
# DYLD_LIBRARY_PATH is for darwin.
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH

View file

@ -207,6 +207,8 @@
<menu action='AudioFileFormatHeader'>
<menuitem action='FileHeaderFormatBWF'/>
<menuitem action='FileHeaderFormatWAVE'/>
<menuitem action='FileHeaderFormatWAVE64'/>
<menuitem action='FileHeaderFormatCAF'/>
</menu>
</menu>
<menu action='Autoconnect'>

View file

@ -50,8 +50,8 @@
#include <ardour/audioengine.h>
#include <ardour/playlist.h>
#include <ardour/utils.h>
#include <ardour/diskstream.h>
#include <ardour/filesource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audiofilesource.h>
#include <ardour/recent_sessions.h>
#include <ardour/session_diskstream.h>
#include <ardour/port.h>
@ -184,9 +184,9 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
gettimeofday (&last_peak_grab, 0);
gettimeofday (&last_shuttle_request, 0);
ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
ARDOUR::AudioDiskstream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
ARDOUR::AudioDiskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
ARDOUR::AudioDiskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
/* handle pending state with a dialog */
@ -241,10 +241,10 @@ ARDOUR_UI::set_engine (AudioEngine& e)
/* this being a GUI and all, we want peakfiles */
FileSource::set_build_peakfiles (true);
FileSource::set_build_missing_peakfiles (true);
AudioFileSource::set_build_peakfiles (true);
AudioFileSource::set_build_missing_peakfiles (true);
if (Source::start_peak_thread ()) {
if (AudioSource::start_peak_thread ()) {
throw failed_constructor();
}
@ -281,7 +281,7 @@ ARDOUR_UI::~ARDOUR_UI ()
delete add_route_dialog;
}
Source::stop_peak_thread ();
AudioSource::stop_peak_thread ();
}
gint
@ -542,7 +542,7 @@ ARDOUR_UI::update_buffer_load ()
}
void
ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
ARDOUR_UI::count_recenabled_diskstreams (AudioDiskstream& ds)
{
if (ds.record_enabled()) {
rec_enabled_diskstreams++;
@ -570,7 +570,7 @@ ARDOUR_UI::update_disk_space()
if (session->actively_recording()){
rec_enabled_diskstreams = 0;
session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
session->foreach_audio_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
if (rec_enabled_diskstreams) {
frames /= rec_enabled_diskstreams;
@ -917,7 +917,7 @@ restart JACK with more ports."));
}
void
ARDOUR_UI::diskstream_added (DiskStream* ds)
ARDOUR_UI::diskstream_added (AudioDiskstream* ds)
{
}
@ -1164,7 +1164,7 @@ ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
return;
}
DiskStream *ds;
AudioDiskstream *ds;
if ((ds = session->diskstream_by_id (dstream)) != 0) {
Port *port = ds->io()->input (0);
@ -1179,7 +1179,7 @@ ARDOUR_UI::toggle_record_enable (guint32 dstream)
return;
}
DiskStream *ds;
AudioDiskstream *ds;
if ((ds = session->diskstream_by_id (dstream)) != 0) {
ds->set_record_enabled (!ds->record_enabled(), this);
@ -1386,7 +1386,7 @@ ARDOUR_UI::stop_blinking ()
void
ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
ARDOUR_UI::add_diskstream_to_menu (AudioDiskstream& dstream)
{
using namespace Gtk;
using namespace Menu_Helpers;
@ -1424,7 +1424,7 @@ ARDOUR_UI::select_diskstream (GdkEventButton *ev)
MenuList& items = diskstream_menu->items();
items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
session->foreach_audio_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
if (ev) {
diskstream_menu->popup (ev->button, ev->time);
@ -1569,7 +1569,7 @@ ARDOUR_UI::secondary_clock_value_changed ()
}
void
ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
{
if (session && dstream && dstream->record_enabled()) {
@ -2216,11 +2216,11 @@ ARDOUR_UI::halt_on_xrun_message ()
}
void
ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>* deletion_list)
{
ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
for (list<AudioFileSource*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
delete *i;
}
@ -2377,6 +2377,12 @@ ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
case RF64:
act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
break;
case CAF:
act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
break;
case AIFF:
act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
break;
}
if (act) {
@ -2451,6 +2457,12 @@ ARDOUR_UI::use_config ()
case RF64:
act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
break;
case CAF:
act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
break;
case AIFF:
act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
break;
}
if (act) {

View file

@ -167,7 +167,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
blinking rec-enable buttons.
*/
void rec_enable_button_blink (bool onoff, ARDOUR::DiskStream *, Gtk::Widget *w);
void rec_enable_button_blink (bool onoff, ARDOUR::AudioDiskstream *, Gtk::Widget *w);
void name_io_setup (ARDOUR::AudioEngine&, string&, ARDOUR::IO& io, bool in);
void choose_io (ARDOUR::IO&, bool input);
@ -522,7 +522,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
sigc::connection point_one_second_connection;
sigc::connection point_zero_one_second_connection;
void diskstream_added (ARDOUR::DiskStream*);
void diskstream_added (ARDOUR::AudioDiskstream*);
gint session_menu (GdkEventButton *);
@ -539,7 +539,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode);
void add_diskstream_to_menu (ARDOUR::DiskStream&);
void add_diskstream_to_menu (ARDOUR::AudioDiskstream&);
void diskstream_selected (gint32);
Gtk::Menu *diskstream_menu;
gint32 selected_dstream;
@ -630,7 +630,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_monitor_enable (guint32);
uint32_t rec_enabled_diskstreams;
void count_recenabled_diskstreams (ARDOUR::DiskStream&);
void count_recenabled_diskstreams (ARDOUR::AudioDiskstream&);
About* about;
bool shown_flag;
@ -649,7 +649,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
struct timeval last_peak_grab;
struct timeval last_shuttle_request;
void delete_sources_in_the_right_thread (list<ARDOUR::Source*>*);
void delete_sources_in_the_right_thread (list<ARDOUR::AudioFileSource*>*);
void editor_display_control_changed (Editing::DisplayControl c);

View file

@ -75,8 +75,8 @@ ARDOUR_UI::connect_to_session (Session *s)
rec_button.set_sensitive (true);
shuttle_box.set_sensitive (true);
if (session->n_diskstreams() == 0) {
session->DiskStreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
if (session->n_audio_diskstreams() == 0) {
session->AudioDiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
}
if (connection_editor) {

View file

@ -381,8 +381,9 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatBWF"), X_("Broadcast WAVE"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::BWF));
act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatWAVE"), X_("WAVE"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::WAVE));
act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatWAVE64"), X_("WAVE-64"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::WAVE64));
act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatiXML"), X_("iXML"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::iXML));
act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatRF64"), X_("RF64"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::RF64));
// act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatiXML"), X_("iXML"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::iXML));
// act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatRF64"), X_("RF64"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::RF64));
act = ActionManager::register_radio_action (option_actions, file_header_group, X_("FileHeaderFormatCAF"), X_("CAF"), bind (mem_fun (*this, &ARDOUR_UI::set_native_file_header_format), ARDOUR::CAF));
RadioAction::Group file_data_group;

View file

@ -195,6 +195,8 @@ AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool
clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
if (editable) {
setup_events ();
}
@ -389,6 +391,25 @@ AudioClock::set (jack_nframes_t when, bool force)
last_when = when;
}
void
AudioClock::smpte_offset_changed ()
{
jack_nframes_t current;
switch (_mode) {
case SMPTE:
if (is_duration) {
current = current_duration();
} else {
current = current_time ();
}
set (current, true);
break;
default:
break;
}
}
void
AudioClock::set_frames (jack_nframes_t when, bool force)
{
@ -446,9 +467,9 @@ AudioClock::set_smpte (jack_nframes_t when, bool force)
if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
if (smpte.negative) {
sprintf (buf, "-%02ld", smpte.hours);
sprintf (buf, "-%02" PRIu32, smpte.hours);
} else {
sprintf (buf, " %02ld", smpte.hours);
sprintf (buf, " %02" PRIu32, smpte.hours);
}
hours_label.set_text (buf);
last_hrs = smpte.hours;
@ -456,19 +477,19 @@ AudioClock::set_smpte (jack_nframes_t when, bool force)
}
if (force || smpte.minutes != last_mins) {
sprintf (buf, "%02ld", smpte.minutes);
sprintf (buf, "%02" PRIu32, smpte.minutes);
minutes_label.set_text (buf);
last_mins = smpte.minutes;
}
if (force || smpte.seconds != last_secs) {
sprintf (buf, "%02ld", smpte.seconds);
sprintf (buf, "%02" PRIu32, smpte.seconds);
seconds_label.set_text (buf);
last_secs = smpte.seconds;
}
if (force || smpte.frames != last_frames) {
sprintf (buf, "%02ld", smpte.frames);
sprintf (buf, "%02" PRIu32, smpte.frames);
frames_label.set_text (buf);
last_frames = smpte.frames;
}

View file

@ -175,6 +175,8 @@ class AudioClock : public Gtk::HBox
void build_ops_menu ();
void setup_events ();
void smpte_offset_changed ();
static const uint32_t field_length[(int)AudioFrames+1];
};

View file

@ -38,7 +38,7 @@
#include <gtkmm2ext/utils.h>
#include <ardour/audioplaylist.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/insert.h>
#include <ardour/ladspa_plugin.h>
#include <ardour/location.h>
@ -823,7 +823,7 @@ AudioTimeAxisView::rename_current_playlist ()
string name;
AudioPlaylist *pl;
DiskStream *ds;
AudioDiskstream *ds;
if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
return;
@ -851,7 +851,7 @@ void
AudioTimeAxisView::use_copy_playlist (bool prompt)
{
AudioPlaylist *pl;
DiskStream *ds;
AudioDiskstream *ds;
string name;
if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
@ -891,7 +891,7 @@ void
AudioTimeAxisView::use_new_playlist (bool prompt)
{
AudioPlaylist *pl;
DiskStream *ds;
AudioDiskstream *ds;
string name;
if (((ds = get_diskstream()) == 0) || ds->destructive() || ((pl = ds->playlist()) == 0)) {
@ -930,7 +930,7 @@ void
AudioTimeAxisView::clear_playlist ()
{
AudioPlaylist *pl;
DiskStream *ds;
AudioDiskstream *ds;
if ((ds = get_diskstream()) != 0) {
if ((pl = ds->playlist()) != 0) {
@ -988,7 +988,7 @@ AudioTimeAxisView::diskstream_changed (void *src)
void
AudioTimeAxisView::update_diskstream_display ()
{
DiskStream *ds;
AudioDiskstream *ds;
if ((ds = get_diskstream()) != 0) {
set_playlist (ds->playlist ());
@ -1092,7 +1092,7 @@ AudioTimeAxisView::name() const
Playlist *
AudioTimeAxisView::playlist () const
{
DiskStream *ds;
AudioDiskstream *ds;
if ((ds = get_diskstream()) != 0) {
return ds->playlist();
@ -1142,7 +1142,7 @@ AudioTimeAxisView::hide_click ()
Region*
AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
{
DiskStream *stream;
AudioDiskstream *stream;
AudioPlaylist *playlist;
if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
@ -1717,7 +1717,7 @@ bool
AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
{
Playlist* what_we_got;
DiskStream* ds = get_diskstream();
AudioDiskstream* ds = get_diskstream();
Playlist* playlist;
bool ret = false;

View file

@ -48,7 +48,7 @@ namespace ALSA {
namespace ARDOUR {
class Session;
class DiskStream;
class AudioDiskstream;
class RouteGroup;
class Redirect;
class Insert;

View file

@ -34,6 +34,7 @@
#include <ardour/session.h>
#include <ardour/auditioner.h>
#include <ardour/audioplaylist.h>
#include <ardour/audiosource.h>
#include <ardour/playlist_templates.h>
#include <gtkmm2ext/gtk_ui.h>

View file

@ -38,7 +38,7 @@
#include <gtkmm2ext/utils.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/plugin_manager.h>
#include <ardour/location.h>
#include <ardour/audioplaylist.h>
@ -1636,7 +1636,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
DiskStream* ds;
AudioDiskstream* ds;
Playlist* pl;
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
@ -1663,7 +1663,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
if (atv) {
DiskStream* ds;
AudioDiskstream* ds;
Playlist* pl;
AudioPlaylist* apl;
@ -3107,7 +3107,7 @@ Editor::mapped_set_selected_regionview_from_click (AudioTimeAxisView& atv, uint3
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
DiskStream* ds;
AudioDiskstream* ds;
if ((ds = atv.get_diskstream()) == 0) {
/* bus */
@ -3338,7 +3338,7 @@ Editor::set_selected_regionview_from_region_list (Region& r, Selection::Operatio
AudioPlaylist* pl;
vector<AudioRegion*> results;
AudioRegionView* marv;
DiskStream* ds;
AudioDiskstream* ds;
if ((ds = tatv->get_diskstream()) == 0) {
/* bus */

View file

@ -45,7 +45,6 @@
#include <ardour/tempo.h>
#include <ardour/location.h>
#include <ardour/region.h>
#include <ardour/externalsource.h>
#include "audio_clock.h"
#include "gtk-custom-ruler.h"
@ -67,9 +66,8 @@ namespace LinuxAudioSystems {
}
namespace ARDOUR {
class DiskStream;
class AudioDiskstream;
class RouteGroup;
class Source;
class Playlist;
class Region;
class Location;

View file

@ -26,12 +26,11 @@
#include <ardour/session.h>
#include <ardour/audioplaylist.h>
#include <ardour/audioregion.h>
#include <ardour/diskstream.h>
#include <ardour/filesource.h>
#include <ardour/externalsource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/utils.h>
#include <ardour/audio_track.h>
#include <ardour/audioplaylist.h>
#include <ardour/audiofilesource.h>
#include "ardour_ui.h"
#include "editor.h"
@ -187,7 +186,7 @@ int
Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool& check_sample_rate, ImportMode mode,
AudioTrack* track, jack_nframes_t& pos, bool prompt)
{
ExternalSource *source = 0; /* keep g++ quiet */
AudioFileSource *source = 0; /* keep g++ quiet */
AudioRegion::SourceList sources;
AudioRegion* region;
string idspec;
@ -220,7 +219,7 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
string error_msg;
if (!ExternalSource::get_soundfile_info (path, finfo, error_msg)) {
if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg;
return 0;
}
@ -267,7 +266,7 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
idspec += string_compose(":%1", n);
try {
source = ExternalSource::create (idspec.c_str());
source = AudioFileSource::create (idspec.c_str());
sources.push_back(source);
}

View file

@ -1,5 +1,5 @@
#include <ardour/location.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include "editor.h"
#include "editing.h"

View file

@ -21,7 +21,7 @@
#include <cstdlib>
#include <cmath>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audioplaylist.h>
#include "editor.h"

View file

@ -37,8 +37,8 @@
#include <ardour/types.h>
#include <ardour/export.h>
#include <ardour/audio_track.h>
#include <ardour/filesource.h>
#include <ardour/diskstream.h>
#include <ardour/audiofilesource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audioregion.h>
#include <ardour/audioplaylist.h>
@ -154,7 +154,7 @@ Editor::bounce_region_selection ()
bool
Editor::write_region (string path, AudioRegion& region)
{
FileSource* fs;
AudioFileSource* fs;
const jack_nframes_t chunk_size = 4096;
jack_nframes_t to_read;
Sample buf[chunk_size];
@ -163,7 +163,7 @@ Editor::write_region (string path, AudioRegion& region)
jack_nframes_t pos;
char s[PATH_MAX+1];
uint32_t cnt;
vector<FileSource *> sources;
vector<AudioFileSource *> sources;
uint32_t nchans;
nchans = region.n_channels();
@ -204,7 +204,7 @@ Editor::write_region (string path, AudioRegion& region)
try {
fs = new FileSource (path, session->frame_rate());
fs = AudioFileSource::create (path);
}
catch (failed_constructor& err) {
@ -227,7 +227,7 @@ Editor::write_region (string path, AudioRegion& region)
this_time = min (to_read, chunk_size);
for (vector<FileSource *>::iterator src=sources.begin(); src != sources.end(); ++src) {
for (vector<AudioFileSource *>::iterator src=sources.begin(); src != sources.end(); ++src) {
fs = (*src);
@ -250,7 +250,7 @@ Editor::write_region (string path, AudioRegion& region)
time (&tnow);
now = localtime (&tnow);
for (vector<FileSource *>::iterator src = sources.begin(); src != sources.end(); ++src) {
for (vector<AudioFileSource *>::iterator src = sources.begin(); src != sources.end(); ++src) {
(*src)->update_header (0, *now, tnow);
}
@ -258,7 +258,8 @@ Editor::write_region (string path, AudioRegion& region)
error_out:
for (vector<FileSource*>::iterator i = sources.begin(); i != sources.end(); ++i) {
for (vector<AudioFileSource*>::iterator i = sources.begin(); i != sources.end(); ++i) {
(*i)->mark_for_remove ();
delete (*i);
}
@ -300,7 +301,7 @@ Editor::write_audio_selection (TimeSelection& ts)
bool
Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRange>& range)
{
FileSource* fs;
AudioFileSource* fs;
const jack_nframes_t chunk_size = 4096;
jack_nframes_t nframes;
Sample buf[chunk_size];
@ -310,7 +311,7 @@ Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRang
char s[PATH_MAX+1];
uint32_t cnt;
string path;
vector<FileSource *> sources;
vector<AudioFileSource *> sources;
for (uint32_t n=0; n < channels; ++n) {
@ -337,7 +338,7 @@ Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRang
path = s;
try {
fs = new FileSource (path, session->frame_rate());
fs = AudioFileSource::create (path);
}
catch (failed_constructor& err) {
@ -420,7 +421,7 @@ Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRang
error_out:
/* unref created files */
for (vector<FileSource*>::iterator i = sources.begin(); i != sources.end(); ++i) {
for (vector<AudioFileSource*>::iterator i = sources.begin(); i != sources.end(); ++i) {
(*i)->mark_for_remove ();
delete *i;
}

View file

@ -47,7 +47,7 @@
#include <ardour/types.h>
#include <ardour/route.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/playlist.h>
#include <ardour/audioplaylist.h>
#include <ardour/audioregion.h>
@ -286,7 +286,7 @@ Editor::step_mouse_mode (bool next)
void
Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
bool commit;
bool commit = false;
bool c1;
bool c2;

View file

@ -36,9 +36,7 @@
#include <ardour/session.h>
#include <ardour/audioplaylist.h>
#include <ardour/audioregion.h>
#include <ardour/diskstream.h>
#include <ardour/filesource.h>
#include <ardour/externalsource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/utils.h>
#include <ardour/location.h>
#include <ardour/named_selection.h>
@ -122,9 +120,9 @@ Editor::set_meter_hold (int32_t cnt)
void
Editor::set_meter_falloff (int intval)
{
float val;
float val = 0.0f; /* off */
std::string str;
cerr << "set_meter_falloff () called: intval = " << intval << endl;
Config->set_meter_falloff_off(false);
Config->set_meter_falloff_slowest(false);
Config->set_meter_falloff_slow(false);

View file

@ -26,6 +26,7 @@
#include <pbd/basename.h>
#include <ardour/audioregion.h>
#include <ardour/audiosource.h>
#include <ardour/session_region.h>
#include <gtkmm2ext/stop_signal.h>

View file

@ -36,7 +36,7 @@
#include <ardour/audioplaylist.h>
#include <ardour/audio_track.h>
#include <ardour/audioregion.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include "i18n.h"

View file

@ -31,7 +31,7 @@
#include <ardour/port.h>
#include <ardour/insert.h>
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <gtkmm2ext/doi.h>
#include <gtkmm2ext/gtk_ui.h>

View file

@ -458,7 +458,6 @@ main (int argc, char *argv[])
ui = 0;
}
out:
delete engine;
ARDOUR::cleanup ();
shutdown (0);

View file

@ -20,7 +20,7 @@
#include <ardour/session.h>
#include <ardour/session_route.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audio_track.h>
#include "ardour_ui.h"

View file

@ -37,7 +37,7 @@
#include <ardour/audioengine.h>
#include <ardour/route.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/panner.h>
#include <ardour/send.h>
#include <ardour/insert.h>
@ -665,9 +665,9 @@ MixerStrip::select_stream_input ()
MenuList& items = stream_menu->items();
stream_menu->set_name ("ArdourContextMenu");
Session::DiskStreamList streams = _session.disk_streams();
Session::AudioDiskstreamList streams = _session.audio_disk_streams();
for (Session::DiskStreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
for (Session::AudioDiskstreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
if (!(*i)->hidden()) {
@ -685,7 +685,7 @@ MixerStrip::select_stream_input ()
}
void
MixerStrip::stream_input_chosen (DiskStream *stream)
MixerStrip::stream_input_chosen (AudioDiskstream *stream)
{
if (is_audio_track()) {
audio_track()->set_diskstream (*stream, this);

View file

@ -170,7 +170,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
Gtk::Menu output_menu;
void add_connection_to_output_menu (ARDOUR::Connection *);
void stream_input_chosen (ARDOUR::DiskStream*);
void stream_input_chosen (ARDOUR::AudioDiskstream*);
void select_stream_input ();
void connection_input_chosen (ARDOUR::Connection *);
void connection_output_chosen (ARDOUR::Connection *);

View file

@ -34,7 +34,7 @@
#include <ardour/session.h>
#include <ardour/audio_track.h>
#include <ardour/session_route.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/plugin_manager.h>
#include "mixer_ui.h"

View file

@ -45,7 +45,7 @@ namespace ARDOUR {
class Route;
class RouteGroup;
class Session;
class DiskStream;
class AudioDiskstream;
class AudioEngine;
};

View file

@ -83,7 +83,7 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
{ "name", 1, 0, 'c' },
{ "novst", 0, 0, 'V' },
{ "new", 1, 0, 'N' },
{ "use-hw-optimizations", 0, 0, 'o' },
{ "no-hw-optimizations", 0, 0, 'O' },
{ "curvetest", 1, 0, 'C' },
{ "gtktheme", 0, 0, 'g' },
{ 0, 0, 0, 0 }
@ -124,8 +124,8 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
session_name = optarg;
break;
case 'o':
try_hw_optimization = true;
case 'O':
try_hw_optimization = false;
break;
case 'V':

View file

@ -22,7 +22,7 @@
#include <gtkmm/button.h>
#include <ardour/session_playlist.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/playlist.h>
#include <ardour/audio_track.h>
#include <ardour/audioplaylist.h>
@ -89,7 +89,7 @@ void
PlaylistSelector::show_for (RouteUI* ruix)
{
vector<const char*> item;
DiskStream* this_ds;
AudioDiskstream* this_ds;
string str;
rui = ruix;
@ -115,7 +115,7 @@ PlaylistSelector::show_for (RouteUI* ruix)
for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
DiskStream* ds = session->diskstream_by_id (x->first);
AudioDiskstream* ds = session->diskstream_by_id (x->first);
if (ds == 0) {
continue;

View file

@ -38,7 +38,7 @@
#include <ardour/audioengine.h>
#include <ardour/route.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/send.h>
#include <ardour/insert.h>
#include <ardour/ladspa_plugin.h>

View file

@ -27,7 +27,8 @@
#include <ardour/playlist.h>
#include <ardour/audioregion.h>
#include <ardour/diskstream.h>
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
#include "streamview.h"
#include "regionview.h"

View file

@ -26,7 +26,7 @@
#include <ardour/session.h>
#include <ardour/session_route.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/plugin.h>
#include <ardour/plugin_manager.h>
#include <ardour/ardour.h>

View file

@ -34,7 +34,7 @@
#include <ardour/route.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include "i18n.h"
using namespace sigc;
@ -433,7 +433,13 @@ RouteUI::refresh_remote_control_menu ()
limit += 4; /* leave some breathing room */
for (uint32_t i = 0; i < limit; ++i) {
rc_items.push_back (RadioMenuElem (rc_group, _("None")));
if (_route.remote_control_id() == 0) {
rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
rc_active->set_active ();
}
for (uint32_t i = 1; i < limit; ++i) {
snprintf (buf, sizeof (buf), "%u", i);
rc_items.push_back (RadioMenuElem (rc_group, buf));
rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
@ -872,7 +878,7 @@ RouteUI::is_audio_track () const
return dynamic_cast<AudioTrack*>(&_route) != 0;
}
DiskStream*
AudioDiskstream*
RouteUI::get_diskstream () const
{
AudioTrack *at;

View file

@ -50,7 +50,7 @@ class RouteUI : public virtual AxisView
virtual ~RouteUI();
bool is_audio_track() const;
ARDOUR::DiskStream* get_diskstream() const;
ARDOUR::AudioDiskstream* get_diskstream() const;
ARDOUR::Route& route() const { return _route; }
ARDOUR::AudioTrack* audio_track() const;
@ -116,7 +116,7 @@ class RouteUI : public virtual AxisView
sigc::connection blink_connection;
void rec_enable_button_blink (bool onoff, ARDOUR::DiskStream *, Gtk::Widget *w);
void rec_enable_button_blink (bool onoff, ARDOUR::AudioDiskstream *, Gtk::Widget *w);
void remove_this_route ();
static gint idle_remove_this_route (RouteUI *);

View file

@ -31,7 +31,7 @@
#include <ardour/audio_library.h>
#include <ardour/audioregion.h>
#include <ardour/externalsource.h>
#include <ardour/audiofilesource.h>
#include "ardour_ui.h"
#include "gui_thread.h"
@ -122,7 +122,7 @@ SoundFileBox::setup_labels (string filename)
path = filename;
string error_msg;
if(!ExternalSource::get_soundfile_info (filename, sf_info, error_msg)) {
if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
return false;
}
@ -187,12 +187,12 @@ SoundFileBox::play_btn_clicked ()
if (region_cache.find (path) == region_cache.end()) {
AudioRegion::SourceList srclist;
ExternalSource* sfs;
AudioFileSource* afs;
for (int n = 0; n < sf_info.channels; ++n) {
try {
sfs = ExternalSource::create (path+":"+string_compose("%1", n), false);
srclist.push_back(sfs);
afs = AudioFileSource::create (path+":"+string_compose("%1", n));
srclist.push_back(afs);
} catch (failed_constructor& err) {
error << _("Could not access soundfile: ") << path << endmsg;

View file

@ -40,7 +40,7 @@
#include <gtkmm/treeview.h>
#include <ardour/session.h>
#include <ardour/externalsource.h>
#include <ardour/audiofilesource.h>
#include "ardour_dialog.h"
#include "editing.h"

View file

@ -6,7 +6,8 @@
#include <ardour/audioplaylist.h>
#include <ardour/audioregion.h>
#include <ardour/diskstream.h>
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audio_track.h>
#include <ardour/playlist_templates.h>
#include <ardour/source.h>
@ -311,7 +312,7 @@ StreamView::undisplay_diskstream ()
}
void
StreamView::display_diskstream (DiskStream *ds)
StreamView::display_diskstream (AudioDiskstream *ds)
{
playlist_change_connection.disconnect();
playlist_changed (ds);
@ -337,7 +338,7 @@ StreamView::playlist_modified ()
}
void
StreamView::playlist_changed (DiskStream *ds)
StreamView::playlist_changed (AudioDiskstream *ds)
{
ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds));
@ -491,7 +492,7 @@ StreamView::diskstream_changed (void *src_ignored)
AudioTrack *at;
if ((at = _trackview.audio_track()) != 0) {
DiskStream& ds = at->disk_stream();
AudioDiskstream& ds = at->disk_stream();
/* XXX grrr: when will SigC++ allow me to bind references? */
Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), &ds));
} else {
@ -634,7 +635,7 @@ StreamView::setup_rec_box ()
peak_ready_connections.clear();
for (uint32_t n=0; n < _trackview.get_diskstream()->n_channels(); ++n) {
Source *src = (Source *) _trackview.get_diskstream()->write_source (n);
AudioSource *src = (AudioSource *) _trackview.get_diskstream()->write_source (n);
if (src) {
sources.push_back (src);
peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &StreamView::rec_peak_range_ready), src)));
@ -662,7 +663,7 @@ StreamView::setup_rec_box ()
AudioTrack* at;
at = _trackview.audio_track(); /* we know what it is already */
DiskStream& ds = at->disk_stream();
AudioDiskstream& ds = at->disk_stream();
jack_nframes_t frame_pos = ds.current_capture_start ();
gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
gdouble xend;

View file

@ -37,7 +37,7 @@ namespace Gdk {
namespace ARDOUR {
class Route;
class DiskStream;
class AudioDiskstream;
class Crossfade;
class PeakData;
class AudioRegion;
@ -151,12 +151,12 @@ class StreamView : public sigc::trackable
void remove_audio_region_view (ARDOUR::AudioRegion* );
void remove_audio_rec_region (ARDOUR::AudioRegion*);
void display_diskstream (ARDOUR::DiskStream* );
void display_diskstream (ARDOUR::AudioDiskstream* );
void undisplay_diskstream ();
void redisplay_diskstream ();
void diskstream_changed (void* );
void playlist_state_changed (ARDOUR::Change);
void playlist_changed (ARDOUR::DiskStream* );
void playlist_changed (ARDOUR::AudioDiskstream* );
void playlist_modified ();
bool crossfades_visible;

View file

@ -27,7 +27,8 @@
#include <ardour/playlist.h>
#include <ardour/audioregion.h>
#include <ardour/diskstream.h>
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
#include "taperegionview.h"
#include "audio_time_axis.h"

View file

@ -27,12 +27,15 @@ ardour.Append(POTFILE = domain + '.pot')
ardour.Append(CPPPATH = '#libs/surfaces/control_protocol')
ardour_files=Split("""
audio_diskstream.cc
audio_library.cc
audio_playlist.cc
audio_track.cc
audioengine.cc
audiofilesource.cc
audiofilter.cc
audioregion.cc
audiosource.cc
auditioner.cc
automation.cc
automation_event.cc
@ -44,9 +47,6 @@ curve.cc
cycle_timer.cc
default_click.cc
destructive_filesource.cc
diskstream.cc
externalsource.cc
filesource.cc
gain.cc
gdither.cc
globals.cc

View file

@ -26,7 +26,7 @@
namespace ARDOUR {
class Session;
class DiskStream;
class AudioDiskstream;
class AudioPlaylist;
class RouteGroup;
@ -52,8 +52,8 @@ class AudioTrack : public Route
bool can_record() const { return true; }
void set_record_enable (bool yn, void *src);
DiskStream& disk_stream() const { return *diskstream; }
int set_diskstream (DiskStream&, void *);
AudioDiskstream& disk_stream() const { return *diskstream; }
int set_diskstream (AudioDiskstream&, void *);
int use_diskstream (string name);
int use_diskstream (id_t id);
@ -99,7 +99,7 @@ class AudioTrack : public Route
void set_meter_point (MeterPoint, void* src);
protected:
DiskStream *diskstream;
AudioDiskstream *diskstream;
MeterPoint _saved_meter_point;
TrackMode _mode;

View file

@ -28,7 +28,6 @@ namespace ARDOUR {
class AudioRegion;
class Session;
class FileSource;
class AudioFilter {
@ -37,7 +36,6 @@ class AudioFilter {
: session (s){}
virtual ~AudioFilter() {}
virtual int run (ARDOUR::AudioRegion&) = 0;
std::vector<ARDOUR::AudioRegion*> results;

View file

@ -27,7 +27,6 @@
#include <pbd/undo.h>
#include <ardour/ardour.h>
#include <ardour/source.h>
#include <ardour/gain.h>
#include <ardour/region.h>
#include <ardour/export.h>
@ -40,6 +39,7 @@ class Route;
class Playlist;
class Session;
class AudioFilter;
class AudioSource;
struct AudioRegionState : public RegionState
{
@ -56,7 +56,7 @@ struct AudioRegionState : public RegionState
class AudioRegion : public Region
{
public:
typedef vector<Source *> SourceList;
typedef vector<AudioSource *> SourceList;
static Change FadeInChanged;
static Change FadeOutChanged;
@ -66,12 +66,12 @@ class AudioRegion : public Region
static Change ScaleAmplitudeChanged;
static Change EnvelopeChanged;
AudioRegion (Source&, jack_nframes_t start, jack_nframes_t length, bool announce = true);
AudioRegion (Source&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
AudioRegion (AudioSource&, jack_nframes_t start, jack_nframes_t length, bool announce = true);
AudioRegion (AudioSource&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
AudioRegion (SourceList &, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
AudioRegion (const AudioRegion&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Region::Flag flags = Region::DefaultFlags, bool announce = true);
AudioRegion (const AudioRegion&);
AudioRegion (Source&, const XMLNode&);
AudioRegion (AudioSource&, const XMLNode&);
AudioRegion (SourceList &, const XMLNode&);
~AudioRegion();
@ -85,7 +85,7 @@ class AudioRegion : public Region
void lock_sources ();
void unlock_sources ();
Source& source (uint32_t n=0) const { if (n < sources.size()) return *sources[n]; else return *sources[0]; }
AudioSource& source (uint32_t n=0) const { if (n < sources.size()) return *sources[n]; else return *sources[0]; }
void set_scale_amplitude (gain_t);
gain_t scale_amplitude() const { return _scale_amplitude; }

View file

@ -31,8 +31,11 @@ class CoreAudioSource : public ExternalSource {
CoreAudioSource (const XMLNode&);
~CoreAudioSource ();
jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
float sample_rate() const;
int update_header (jack_nframes_t when, struct tm&, time_t);
protected:
jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
private:
ExtAudioFileRef af;

View file

@ -22,29 +22,27 @@
#define __ardour_cycle_timer_h__
#include <string>
#include <cstdio>
#include <iostream>
#include <ardour/cycles.h>
using std::string;
class CycleTimer {
private:
static float cycles_per_usec;
uint32_t long entry;
uint32_t long exit;
string _name;
cycles_t _entry;
cycles_t _exit;
std::string _name;
public:
CycleTimer(string name) : _name (name){
CycleTimer(std::string name) : _name (name){
if (cycles_per_usec == 0) {
cycles_per_usec = get_mhz ();
}
entry = get_cycles();
_entry = get_cycles();
}
~CycleTimer() {
exit = get_cycles();
printf ("%s: %.9f usecs (%lu-%lu)\n", _name.c_str(), (float) (exit - entry) / cycles_per_usec, entry, exit);
_exit = get_cycles();
std::cerr << _name << ": " << (float) (_exit - _entry) / cycles_per_usec << " (" << _entry << ", " << _exit << ')' << endl;
}
static float get_mhz ();

View file

@ -23,30 +23,33 @@
#include <string>
#include <ardour/filesource.h>
#include <ardour/sndfilesource.h>
struct tm;
namespace ARDOUR {
class DestructiveFileSource : public FileSource {
class DestructiveFileSource : public SndFileSource {
public:
DestructiveFileSource (std::string path, jack_nframes_t rate, bool repair_first = false, SampleFormat samp_format=FormatInt24);
DestructiveFileSource (const XMLNode&, jack_nframes_t rate);
DestructiveFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
AudioFileSource::BuildPeaks));
DestructiveFileSource (const XMLNode&);
~DestructiveFileSource ();
int seek (jack_nframes_t frame);
jack_nframes_t last_capture_start_frame() const;
void mark_capture_start (jack_nframes_t);
void mark_capture_end ();
void clear_capture_marks();
jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf);
XMLNode& get_state ();
static void setup_standard_crossfades (jack_nframes_t sample_rate);
protected:
jack_nframes_t write_unlocked (Sample *src, jack_nframes_t start, jack_nframes_t cnt, char * workbuf);
private:
static jack_nframes_t xfade_frames;
static gain_t* out_coefficient;
@ -59,7 +62,7 @@ class DestructiveFileSource : public FileSource {
Sample* xfade_buf;
jack_nframes_t crossfade (Sample* data, jack_nframes_t cnt, int dir, char * workbuf);
void set_timeline_position (jack_nframes_t);
};
}

View file

@ -37,7 +37,6 @@
#include <ardour/crossfade_compare.h>
#include <ardour/location.h>
#include <ardour/stateful.h>
#include <ardour/source.h>
#include <ardour/state_manager.h>
namespace ARDOUR {

View file

@ -60,11 +60,12 @@ namespace ARDOUR {
class Port;
class AudioEngine;
class Slave;
class DiskStream;
class AudioDiskstream;
class Route;
class AuxInput;
class Source;
class FileSource;
class AudioSource;
class AudioFileSource;
class Auditioner;
class Insert;
class Send;
@ -261,25 +262,30 @@ class Session : public sigc::trackable, public Stateful
vector<Sample*>& get_silent_buffers (uint32_t howmany);
vector<Sample*>& get_send_buffers () { return _send_buffers; }
DiskStream *diskstream_by_id (id_t id);
DiskStream *diskstream_by_name (string name);
AudioDiskstream *diskstream_by_id (id_t id);
AudioDiskstream *diskstream_by_name (string name);
bool have_captured() const { return _have_captured; }
void refill_all_diskstream_buffers ();
uint32_t diskstream_buffer_size() const { return dstream_buffer_size; }
uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
uint32_t n_diskstreams() const;
typedef list<DiskStream *> DiskStreamList;
/* XXX fix required here when we get new diskstream types *, but
not sure of the direction to take this in until then.
*/
Session::DiskStreamList disk_streams() const {
uint32_t get_next_diskstream_id() const { return n_audio_diskstreams(); }
uint32_t n_audio_diskstreams() const;
typedef list<AudioDiskstream *> AudioDiskstreamList;
Session::AudioDiskstreamList audio_disk_streams() const {
Glib::RWLock::ReaderLock lm (diskstream_lock);
return diskstreams; /* XXX yes, force a copy */
return audio_diskstreams; /* XXX yes, force a copy */
}
void foreach_diskstream (void (DiskStream::*func)(void));
template<class T> void foreach_diskstream (T *obj, void (T::*func)(DiskStream&));
void foreach_audio_diskstream (void (AudioDiskstream::*func)(void));
template<class T> void foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&));
typedef list<Route *> RouteList;
@ -344,7 +350,7 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void> HaltOnXrun;
sigc::signal<void,Route*> RouteAdded;
sigc::signal<void,DiskStream*> DiskStreamAdded;
sigc::signal<void,AudioDiskstream*> AudioDiskstreamAdded;
void request_roll ();
void request_bounded_roll (jack_nframes_t start, jack_nframes_t end);
@ -356,15 +362,15 @@ class Session : public sigc::trackable, public Stateful
void goto_start () { request_locate (start_location->start(), false); }
void use_rf_shuttle_speed ();
void request_transport_speed (float speed);
void request_overwrite_buffer (DiskStream*);
void request_diskstream_speed (DiskStream&, float speed);
void request_overwrite_buffer (AudioDiskstream*);
void request_diskstream_speed (AudioDiskstream&, float speed);
void request_input_change_handling ();
bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
bool transport_locked () const;
int wipe ();
int wipe_diskstream (DiskStream *);
int wipe_diskstream (AudioDiskstream *);
int remove_region_from_region_list (Region&);
@ -612,7 +618,7 @@ class Session : public sigc::trackable, public Stateful
jack_nframes_t convert_to_frames_at (jack_nframes_t position, AnyTime&);
sigc::signal<void> SMPTEOffsetChanged;
static sigc::signal<void> SMPTEOffsetChanged;
sigc::signal<void> SMPTETypeChanged;
void request_slave_source (SlaveSource, jack_nframes_t pos = 0);
@ -668,8 +674,9 @@ class Session : public sigc::trackable, public Stateful
int start_audio_export (ARDOUR::AudioExportSpecification&);
int stop_audio_export (ARDOUR::AudioExportSpecification&);
void add_source (Source *);
int remove_file_source (FileSource&);
void add_audio_source (AudioSource *);
void remove_source (Source *);
int cleanup_audio_file_source (AudioFileSource&);
struct cleanup_report {
vector<string> paths;
@ -701,7 +708,8 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void,Source *> SourceAdded;
sigc::signal<void,Source *> SourceRemoved;
FileSource *create_file_source (ARDOUR::DiskStream&, int32_t chan, bool destructive);
AudioFileSource *create_audio_source_for_session (ARDOUR::AudioDiskstream&, uint32_t which_channel, bool destructive);
Source *get_source (ARDOUR::id_t);
/* playlist management */
@ -745,7 +753,7 @@ class Session : public sigc::trackable, public Stateful
/* flattening stuff */
int write_one_track (AudioTrack&, jack_nframes_t start, jack_nframes_t cnt, bool overwrite, vector<Source*>&,
int write_one_audio_track (AudioTrack&, jack_nframes_t start, jack_nframes_t cnt, bool overwrite, vector<AudioSource*>&,
InterThreadInfo& wot);
int freeze (InterThreadInfo&);
@ -972,7 +980,7 @@ class Session : public sigc::trackable, public Stateful
void set_frame_rate (jack_nframes_t nframes);
protected:
friend class DiskStream;
friend class AudioDiskstream;
void stop_butler ();
void wait_till_butler_finished();
@ -1434,12 +1442,12 @@ class Session : public sigc::trackable, public Stateful
bool waiting_to_start;
void set_auto_loop (bool yn);
void overwrite_some_buffers (DiskStream*);
void overwrite_some_buffers (AudioDiskstream*);
void flush_all_redirects ();
void locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void start_locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
void force_locate (jack_nframes_t frame, bool with_roll = false);
void set_diskstream_speed (DiskStream*, float speed);
void set_diskstream_speed (AudioDiskstream*, float speed);
void set_transport_speed (float speed, bool abort = false);
void stop_transport (bool abort = false);
void start_transport ();
@ -1470,10 +1478,10 @@ class Session : public sigc::trackable, public Stateful
/* disk-streams */
DiskStreamList diskstreams;
AudioDiskstreamList audio_diskstreams;
mutable Glib::RWLock diskstream_lock;
uint32_t dstream_buffer_size;
void add_diskstream (DiskStream*);
void add_diskstream (AudioDiskstream*);
int load_diskstreams (const XMLNode&);
/* routes stuff */
@ -1515,16 +1523,14 @@ class Session : public sigc::trackable, public Stateful
/* SOURCES */
mutable Glib::Mutex source_lock;
typedef std::map<id_t, Source *> SourceList;
mutable Glib::Mutex audio_source_lock;
typedef std::map<id_t, AudioSource *> AudioSourceList;
SourceList sources;
AudioSourceList audio_sources;
int load_sources (const XMLNode& node);
XMLNode& get_sources_as_xml ();
void remove_source (Source *);
Source *XMLSourceFactory (const XMLNode&);
/* PLAYLISTS */
@ -1543,7 +1549,7 @@ class Session : public sigc::trackable, public Stateful
Playlist *XMLPlaylistFactory (const XMLNode&);
void playlist_length_changed (Playlist *);
void diskstream_playlist_changed (DiskStream *);
void diskstream_playlist_changed (AudioDiskstream *);
/* NAMED SELECTIONS */

View file

@ -22,15 +22,15 @@
#define __ardour_session_diskstream_h__
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
namespace ARDOUR {
template<class T> void
Session::foreach_diskstream (T *obj, void (T::*func)(DiskStream&))
Session::foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&))
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); i++) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); i++) {
if (!(*i)->hidden()) {
(obj->*func) (**i);
}

View file

@ -23,29 +23,57 @@
#include <sndfile.h>
#include <ardour/externalsource.h>
#include <ardour/audiofilesource.h>
namespace ARDOUR {
class SndFileSource : public ExternalSource {
class SndFileSource : public AudioFileSource {
public:
SndFileSource (const string& path_plus_channel, bool build_peak = true);
/* constructor to be called for existing external-to-session files */
SndFileSource (std::string path, Flag flags);
/* constructor to be called for new in-session files */
SndFileSource (std::string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate,
Flag flags = AudioFileSource::Flag (AudioFileSource::Writable|
AudioFileSource::Removable|
AudioFileSource::RemovableIfEmpty|
AudioFileSource::CanRename|
AudioFileSource::BuildPeaks));
/* constructor to be called for existing in-session files */
SndFileSource (const XMLNode&);
~SndFileSource ();
jack_nframes_t length() const { return _info.frames; }
jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
float sample_rate () const;
int update_header (jack_nframes_t when, struct tm&, time_t);
int flush_header ();
static Flag default_in_session_flags();
protected:
void set_header_timeline_position ();
jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
jack_nframes_t write_unlocked (Sample *dst, jack_nframes_t cnt, char * workbuf);
jack_nframes_t write_float (Sample* data, jack_nframes_t pos, jack_nframes_t cnt);
private:
SNDFILE *sf;
SF_INFO _info;
SF_BROADCAST_INFO* _broadcast_info;
mutable float *tmpbuf;
mutable jack_nframes_t tmpbufsize;
mutable Glib::Mutex _tmpbuf_lock;
mutable float *interleave_buf;
mutable jack_nframes_t interleave_bufsize;
void init (const string &str, bool build_peak);
void init (const string &str);
int open();
void close();
int setup_broadcast_info (jack_nframes_t when, struct tm&, time_t);
};
}; /* namespace ARDOUR */

View file

@ -21,166 +21,46 @@
#ifndef __ardour_source_h__
#define __ardour_source_h__
#include <list>
#include <vector>
#include <string>
#include <ctime>
#include <sigc++/signal.h>
#include <glibmm/thread.h>
#include <ardour/ardour.h>
#include <ardour/stateful.h>
#include <pbd/xml++.h>
using std::list;
using std::vector;
using std::string;
namespace ARDOUR {
struct PeakData {
typedef Sample PeakDatum;
PeakDatum min;
PeakDatum max;
};
const jack_nframes_t frames_per_peak = 256;
class Source : public Stateful, public sigc::trackable
{
public:
Source (bool announce=true);
Source (std::string name);
Source (const XMLNode&);
virtual ~Source ();
const string& name() const { return _name; }
std::string name() const { return _name; }
int set_name (std::string str, bool destructive);
ARDOUR::id_t id() const { return _id; }
/* returns the number of items in this `source' */
virtual jack_nframes_t length() const {
return _length;
}
virtual jack_nframes_t available_peaks (double zoom) const;
virtual jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const {
return 0;
}
virtual jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf) {
return 0;
}
virtual float sample_rate () const { return 0; }
uint32_t use_cnt() const { return _use_cnt; }
void use ();
void release ();
virtual void mark_for_remove() = 0;
virtual void mark_streaming_write_completed () {}
time_t timestamp() const { return _timestamp; }
void stamp (time_t when) { _timestamp = when; }
void set_captured_for (string str) { _captured_for = str; }
string captured_for() const { return _captured_for; }
uint32_t read_data_count() const { return _read_data_count; }
uint32_t write_data_count() const { return _write_data_count; }
int read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start, jack_nframes_t cnt, double samples_per_unit) const;
int build_peaks ();
bool peaks_ready (sigc::slot<void>, sigc::connection&) const;
static sigc::signal<void,Source*> SourceCreated;
sigc::signal<void,Source *> GoingAway;
mutable sigc::signal<void> PeaksReady;
mutable sigc::signal<void,jack_nframes_t,jack_nframes_t> PeakRangeReady;
XMLNode& get_state ();
int set_state (const XMLNode&);
static int start_peak_thread ();
static void stop_peak_thread ();
int rename_peakfile (std::string newpath);
static void set_build_missing_peakfiles (bool yn) {
_build_missing_peakfiles = yn;
}
static void set_build_peakfiles (bool yn) {
_build_peakfiles = yn;
}
sigc::signal<void,Source *> GoingAway;
protected:
static bool _build_missing_peakfiles;
static bool _build_peakfiles;
string _name;
uint32_t _use_cnt;
bool _peaks_built;
mutable Glib::Mutex _lock;
jack_nframes_t _length;
bool next_peak_clear_should_notify;
string peakpath;
time_t _timestamp;
string _captured_for;
mutable uint32_t _read_data_count; // modified in read()
mutable uint32_t _write_data_count; // modified in write()
int initialize_peakfile (bool newfile, string path);
void build_peaks_from_scratch ();
int do_build_peak (jack_nframes_t, jack_nframes_t);
virtual jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const = 0;
virtual string peak_path(string audio_path) = 0;
static pthread_t peak_thread;
static bool have_peak_thread;
static void* peak_thread_work(void*);
static int peak_request_pipe[2];
struct PeakRequest {
enum Type {
Build,
Quit
};
};
static vector<Source*> pending_peak_sources;
static Glib::StaticMutex pending_peak_sources_lock;
static void queue_for_peaks (Source&);
static void clear_queue_for_peaks ();
struct PeakBuildRecord {
jack_nframes_t frame;
jack_nframes_t cnt;
PeakBuildRecord (jack_nframes_t f, jack_nframes_t c)
: frame (f), cnt (c) {}
PeakBuildRecord (const PeakBuildRecord& other) {
frame = other.frame;
cnt = other.cnt;
}
};
list<Source::PeakBuildRecord *> pending_peak_builds;
private:
ARDOUR::id_t _id;
bool file_changed (string path);
};
}

View file

@ -255,10 +255,18 @@ namespace ARDOUR {
BWF,
WAVE,
WAVE64,
CAF,
AIFF,
iXML,
RF64
};
struct PeakData {
typedef Sample PeakDatum;
PeakDatum min;
PeakDatum max;
};
};
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);

View file

@ -23,10 +23,11 @@
#include <sigc++/bind.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/session.h>
#include <ardour/redirect.h>
#include <ardour/audioregion.h>
#include <ardour/audiosource.h>
#include <ardour/route_group_specialized.h>
#include <ardour/insert.h>
#include <ardour/audioplaylist.h>
@ -43,19 +44,19 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
diskstream (0),
_midi_rec_enable_control (*this, _session.midi_port())
{
DiskStream::Flag dflags = DiskStream::Flag (0);
AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0);
if (_flags & Hidden) {
dflags = DiskStream::Flag (dflags | DiskStream::Hidden);
dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Hidden);
} else {
dflags = DiskStream::Flag (dflags | DiskStream::Recordable);
dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Recordable);
}
if (mode == Destructive) {
dflags = DiskStream::Flag (dflags | DiskStream::Destructive);
dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
}
DiskStream* ds = new DiskStream (_session, name, dflags);
AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags);
_declickable = true;
_freeze_record.state = NoFreeze;
@ -64,6 +65,8 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
set_diskstream (*ds, this);
// session.SMPTEOffsetChanged.connect (mem_fun (*this, &AudioTrack::handle_smpte_offset_change));
// we do this even though Route already did it in it's init
reset_midi_control (_session.midi_port(), _session.get_midi_control());
@ -90,6 +93,14 @@ AudioTrack::~AudioTrack ()
}
}
#if 0
void
AudioTrack::handle_smpte_offset_change ()
{
diskstream
}
#endif
int
AudioTrack::deprecated_use_diskstream_connections ()
{
@ -143,7 +154,7 @@ AudioTrack::deprecated_use_diskstream_connections ()
}
int
AudioTrack::set_diskstream (DiskStream& ds, void *src)
AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
{
if (diskstream) {
diskstream->unref();
@ -166,7 +177,7 @@ AudioTrack::set_diskstream (DiskStream& ds, void *src)
diskstream->monitor_input (false);
ic_connection.disconnect();
ic_connection = input_changed.connect (mem_fun (*diskstream, &DiskStream::handle_input_change));
ic_connection = input_changed.connect (mem_fun (*diskstream, &AudioDiskstream::handle_input_change));
diskstream_changed (src); /* EMIT SIGNAL */
@ -176,7 +187,7 @@ AudioTrack::set_diskstream (DiskStream& ds, void *src)
int
AudioTrack::use_diskstream (string name)
{
DiskStream *dstream;
AudioDiskstream *dstream;
if ((dstream = _session.diskstream_by_name (name)) == 0) {
error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg;
@ -189,7 +200,7 @@ AudioTrack::use_diskstream (string name)
int
AudioTrack::use_diskstream (id_t id)
{
DiskStream *dstream;
AudioDiskstream *dstream;
if ((dstream = _session.diskstream_by_id (id)) == 0) {
error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg;
@ -899,23 +910,23 @@ AudioTrack::update_total_latency ()
void
AudioTrack::bounce (InterThreadInfo& itt)
{
vector<Source*> srcs;
_session.write_one_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
vector<AudioSource*> srcs;
_session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
}
void
AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
{
vector<Source*> srcs;
_session.write_one_track (*this, start, end, false, srcs, itt);
vector<AudioSource*> srcs;
_session.write_one_audio_track (*this, start, end, false, srcs, itt);
}
void
AudioTrack::freeze (InterThreadInfo& itt)
{
Insert* insert;
vector<Source*> srcs;
vector<AudioSource*> srcs;
string new_playlist_name;
Playlist* new_playlist;
string dir;
@ -950,7 +961,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
return;
}
if (_session.write_one_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
if (_session.write_one_audio_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
return;
}

View file

@ -229,6 +229,7 @@ AudioEngine::_freewheel_callback (int onoff, void *arg)
int
AudioEngine::process_callback (jack_nframes_t nframes)
{
// CycleTimer ct ("AudioEngine::process");
Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK);
jack_nframes_t next_processed_frames;

View file

@ -22,7 +22,7 @@
#include <cerrno>
#include <pbd/basename.h>
#include <ardour/filesource.h>
#include <ardour/sndfilesource.h>
#include <ardour/session.h>
#include <ardour/audioregion.h>
#include <ardour/audiofilter.h>
@ -47,7 +47,10 @@ AudioFilter::make_new_sources (AudioRegion& region, AudioRegion::SourceList& nsr
}
try {
nsrcs.push_back (new FileSource (path, session.frame_rate(), false, Config->get_native_file_data_format()));
nsrcs.push_back (new SndFileSource (path,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
session.frame_rate()));
}
catch (failed_constructor& err) {
@ -73,7 +76,10 @@ AudioFilter::finish (AudioRegion& region, AudioRegion::SourceList& nsrcs)
now = localtime (&xnow);
for (AudioRegion::SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
dynamic_cast<FileSource*>((*si))->update_header (region.position(), *now, xnow);
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*si);
if (afs) {
afs->update_header (region.position(), *now, xnow);
}
}
/* create a new region */

View file

@ -38,6 +38,7 @@
#include <ardour/dB.h>
#include <ardour/playlist.h>
#include <ardour/audiofilter.h>
#include <ardour/audiosource.h>
#include "i18n.h"
#include <locale.h>
@ -63,7 +64,7 @@ AudioRegionState::AudioRegionState (string why)
{
}
AudioRegion::AudioRegion (Source& src, jack_nframes_t start, jack_nframes_t length, bool announce)
AudioRegion::AudioRegion (AudioSource& src, jack_nframes_t start, jack_nframes_t length, bool announce)
: Region (start, length, PBD::basename_nosuffix(src.name()), 0, Region::Flag(Region::DefaultFlags|Region::External)),
_fade_in (0.0, 2.0, 1.0, false),
_fade_out (0.0, 2.0, 1.0, false),
@ -89,7 +90,7 @@ AudioRegion::AudioRegion (Source& src, jack_nframes_t start, jack_nframes_t leng
}
}
AudioRegion::AudioRegion (Source& src, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t layer, Flag flags, bool announce)
AudioRegion::AudioRegion (AudioSource& src, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t layer, Flag flags, bool announce)
: Region (start, length, name, layer, flags),
_fade_in (0.0, 2.0, 1.0, false),
_fade_out (0.0, 2.0, 1.0, false),
@ -150,7 +151,7 @@ AudioRegion::AudioRegion (const AudioRegion& other, jack_nframes_t offset, jack_
{
/* create a new AudioRegion, that is part of an existing one */
set<Source*> unique_srcs;
set<AudioSource*> unique_srcs;
for (SourceList::const_iterator i= other.sources.begin(); i != other.sources.end(); ++i) {
sources.push_back (*i);
@ -209,7 +210,7 @@ AudioRegion::AudioRegion (const AudioRegion &other)
{
/* Pure copy constructor */
set<Source*> unique_srcs;
set<AudioSource*> unique_srcs;
for (SourceList::const_iterator i = other.sources.begin(); i != other.sources.end(); ++i) {
sources.push_back (*i);
@ -237,7 +238,7 @@ AudioRegion::AudioRegion (const AudioRegion &other)
/* NOTE: no CheckNewRegion signal emitted here. This is the copy constructor */
}
AudioRegion::AudioRegion (Source& src, const XMLNode& node)
AudioRegion::AudioRegion (AudioSource& src, const XMLNode& node)
: Region (node),
_fade_in (0.0, 2.0, 1.0, false),
_fade_out (0.0, 2.0, 1.0, false),
@ -268,7 +269,7 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node)
{
/* basic AudioRegion constructor */
set<Source*> unique_srcs;
set<AudioSource*> unique_srcs;
for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) {
sources.push_back (*i);
@ -1094,7 +1095,7 @@ void
AudioRegion::lock_sources ()
{
SourceList::iterator i;
set<Source*> unique_srcs;
set<AudioSource*> unique_srcs;
for (i = sources.begin(); i != sources.end(); ++i) {
unique_srcs.insert (*i);
@ -1112,7 +1113,7 @@ void
AudioRegion::unlock_sources ()
{
SourceList::iterator i;
set<Source*> unique_srcs;
set<AudioSource*> unique_srcs;
for (i = sources.begin(); i != sources.end(); ++i) {
unique_srcs.insert (*i);

View file

@ -20,7 +20,7 @@
#include <glibmm/thread.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audioregion.h>
#include <ardour/route.h>
#include <ardour/session.h>

View file

@ -26,7 +26,7 @@
#include <ardour/ardour.h>
#include <ardour/configuration.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/destructive_filesource.h>
#include <ardour/control_protocol_manager.h>
@ -231,7 +231,7 @@ Configuration::set_state (const XMLNode& root)
}
}
DiskStream::set_disk_io_chunk_frames (minimum_disk_io_bytes.get() / sizeof (Sample));
AudioDiskstream::set_disk_io_chunk_frames (minimum_disk_io_bytes.get() / sizeof (Sample));
return 0;
}

View file

@ -66,13 +66,9 @@ gain_t* DestructiveFileSource::out_coefficient = 0;
gain_t* DestructiveFileSource::in_coefficient = 0;
jack_nframes_t DestructiveFileSource::xfade_frames = 64;
DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first, SampleFormat samp_format)
: FileSource (path, rate, repair_first, samp_format)
DestructiveFileSource::DestructiveFileSource (string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
: SndFileSource (path, samp_format, hdr_format, rate, flags)
{
if (out_coefficient == 0) {
setup_standard_crossfades (rate);
}
xfade_buf = new Sample[xfade_frames];
_capture_start = false;
@ -80,13 +76,9 @@ DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate,
file_pos = 0;
}
DestructiveFileSource::DestructiveFileSource (const XMLNode& node, jack_nframes_t rate)
: FileSource (node, rate)
DestructiveFileSource::DestructiveFileSource (const XMLNode& node)
: SndFileSource (node)
{
if (out_coefficient == 0) {
setup_standard_crossfades (rate);
}
xfade_buf = new Sample[xfade_frames];
_capture_start = false;
@ -102,6 +94,10 @@ DestructiveFileSource::~DestructiveFileSource()
void
DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate)
{
/* This static method is assumed to have been called by the Session
before any DFS's are created.
*/
xfade_frames = (jack_nframes_t) floor ((Config->get_destructive_xfade_msecs () / 1000.0) * rate);
if (out_coefficient) {
@ -124,12 +120,6 @@ DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate)
}
}
int
DestructiveFileSource::seek (jack_nframes_t frame)
{
return 0;
}
void
DestructiveFileSource::mark_capture_start (jack_nframes_t pos)
{
@ -188,7 +178,7 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in,
}
if (file_cnt) {
if ((retval = file_read (xfade_buf, fade_position, file_cnt, workbuf)) != (ssize_t) file_cnt) {
if ((retval = write_float (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
if (retval >= 0 && errno == EAGAIN) {
/* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you.
* short or no data there */
@ -206,7 +196,7 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in,
}
if (nofade && !fade_in) {
if (file_write (data, file_pos, nofade, workbuf) != (ssize_t) nofade) {
if (write_float (data, file_pos, nofade) != nofade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
@ -248,14 +238,14 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in,
}
if (xfade) {
if (file_write (xfade_buf, fade_position, xfade, workbuf) != (ssize_t) xfade) {
if (write_float (xfade_buf, fade_position, xfade) != xfade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
}
if (fade_in && nofade) {
if (file_write (data + xfade, file_pos + xfade, nofade, workbuf) != (ssize_t) nofade) {
if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
@ -265,13 +255,14 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in,
}
jack_nframes_t
DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf)
DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t start, jack_nframes_t cnt, char * workbuf)
{
{
Glib::Mutex::Lock lm (_lock);
jack_nframes_t old_file_pos;
if (!writable()) {
return 0;
}
if (_capture_start && _capture_end) {
_capture_start = false;
_capture_end = false;
@ -300,6 +291,7 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf)
file_pos = ofilepos; // adjusted below
}
else if (_capture_start) {
_capture_start = false;
_capture_end = false;
@ -311,14 +303,17 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf)
}
} else if (_capture_end) {
_capture_start = false;
_capture_end = false;
if (crossfade (data, cnt, 0, workbuf) != cnt) {
return 0;
}
} else {
if (file_write(data, file_pos, cnt, workbuf) != (ssize_t) cnt) {
if (write_float (data, file_pos, cnt) != cnt) {
return 0;
}
}
@ -349,7 +344,6 @@ DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf)
_peaks_built = false;
}
}
if (_build_peakfiles) {
queue_for_peaks (*this);
@ -367,7 +361,14 @@ DestructiveFileSource::last_capture_start_frame () const
XMLNode&
DestructiveFileSource::get_state ()
{
XMLNode& node = FileSource::get_state ();
XMLNode& node = AudioFileSource::get_state ();
node.add_property (X_("destructive"), "true");
return node;
}
void
DestructiveFileSource::set_timeline_position (jack_nframes_t pos)
{
/* destructive tracks always start at where our reference frame zero is */
timeline_position = 0;
}

View file

@ -62,8 +62,7 @@
#include <ardour/ardour.h>
#include <ardour/version.h>
#include <ardour/source.h>
#include <ardour/filesource.h>
#include <ardour/audiofilesource.h>
#include <ardour/session.h>
#include <ardour/cycle_timer.h>
#include <ardour/pcm_utils.h>

View file

@ -43,7 +43,7 @@
#include <ardour/audio_library.h>
#include <ardour/configuration.h>
#include <ardour/plugin_manager.h>
#include <ardour/source.h>
#include <ardour/audiosource.h>
#include <ardour/utils.h>
#include <ardour/session.h>
#include <ardour/control_protocol_manager.h>

View file

@ -36,8 +36,8 @@
#include <ardour/ardour.h>
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/filesource.h>
#include <ardour/audio_diskstream.h>
#include <ardour/sndfilesource.h>
#include <ardour/sndfile_helpers.h>
#include <ardour/audioregion.h>
@ -51,8 +51,8 @@ int
Session::import_audiofile (import_status& status)
{
SNDFILE *in;
FileSource **newfiles = 0;
ARDOUR::AudioRegion::SourceList sources;
AudioFileSource **newfiles = 0;
AudioRegion::SourceList sources;
SF_INFO info;
float *data = 0;
Sample **channel_data = 0;
@ -94,7 +94,7 @@ Session::import_audiofile (import_status& status)
}
}
newfiles = new FileSource *[info.channels];
newfiles = new AudioFileSource *[info.channels];
for (n = 0; n < info.channels; ++n) {
newfiles[n] = 0;
}
@ -137,7 +137,10 @@ Session::import_audiofile (import_status& status)
try {
newfiles[n] = new FileSource (buf, frame_rate(), false, Config->get_native_file_data_format());
newfiles[n] = new SndFileSource (buf,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
frame_rate ());
}
catch (failed_constructor& err) {

View file

@ -309,7 +309,6 @@ OSC::osc_receiver()
if ((ret = poll (pfd, nfds, timeout)) < 0) {
if (errno == EINTR) {
/* gdb at work, perhaps */
cerr << "EINTR hit " << endl;
goto again;
}

View file

@ -24,7 +24,7 @@
#include <ardour/types.h>
#include <ardour/reverse.h>
#include <ardour/filesource.h>
#include <ardour/audiofilesource.h>
#include <ardour/session.h>
#include <ardour/audioregion.h>

View file

@ -29,7 +29,7 @@
#include <ardour/route_group.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/configuration.h>
using namespace ARDOUR;

View file

@ -32,7 +32,8 @@
#include <sigc++/bind.h>
#include <sigc++/retype.h>
#include <glibmm.h>
#include <glibmm/thread.h>
#include <glibmm/miscutils.h>
#include <pbd/error.h>
#include <glibmm/thread.h>
@ -43,14 +44,12 @@
#include <ardour/audioengine.h>
#include <ardour/configuration.h>
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/utils.h>
#include <ardour/audioplaylist.h>
#include <ardour/audioregion.h>
#include <ardour/source.h>
#include <ardour/filesource.h>
#include <ardour/audiofilesource.h>
#include <ardour/destructive_filesource.h>
#include <ardour/sndfilesource.h>
#include <ardour/auditioner.h>
#include <ardour/recent_sessions.h>
#include <ardour/redirect.h>
@ -90,6 +89,7 @@ Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
sigc::signal<int> Session::AskAboutPendingState;
sigc::signal<void> Session::SMPTEOffsetChanged;
int
Session::find_session (string str, string& path, string& snapshot, bool& isnew)
@ -455,10 +455,10 @@ Session::~Session ()
}
#ifdef TRACK_DESTRUCTION
cerr << "delete diskstreams\n";
cerr << "delete audio_diskstreams\n";
#endif /* TRACK_DESTRUCTION */
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) {
DiskStreamList::iterator tmp;
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ) {
AudioDiskstreamList::iterator tmp;
tmp = i;
++tmp;
@ -469,10 +469,10 @@ Session::~Session ()
}
#ifdef TRACK_DESTRUCTION
cerr << "delete sources\n";
cerr << "delete audio sources\n";
#endif /* TRACK_DESTRUCTION */
for (SourceList::iterator i = sources.begin(); i != sources.end(); ) {
SourceList::iterator tmp;
for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
AudioSourceList::iterator tmp;
tmp = i;
++tmp;
@ -881,7 +881,7 @@ Session::playlist_length_changed (Playlist* pl)
}
void
Session::diskstream_playlist_changed (DiskStream* dstream)
Session::diskstream_playlist_changed (AudioDiskstream* dstream)
{
Playlist *playlist;
@ -961,7 +961,7 @@ Session::set_auto_input (bool yn)
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input);
@ -979,7 +979,7 @@ Session::reset_input_monitor_state ()
{
if (transport_rolling()) {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
@ -987,7 +987,7 @@ Session::reset_input_monitor_state ()
}
} else {
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring());
@ -1068,7 +1068,7 @@ Session::auto_loop_changed (Location* location)
}
else if (seamless_loop && !loop_changing) {
// schedule a locate-roll to refill the diskstreams at the
// schedule a locate-roll to refill the audio_diskstreams at the
// previous loop end
loop_changing = true;
@ -1265,7 +1265,7 @@ Session::enable_record ()
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (true);
}
@ -1300,7 +1300,7 @@ Session::disable_record (bool rt_context, bool force)
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (false);
}
@ -1327,7 +1327,7 @@ Session::step_back_from_record ()
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
@ -1432,6 +1432,9 @@ Session::set_frame_rate (jack_nframes_t frames_per_second)
Route::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * 0.25));
// XXX we need some equivalent to this, somehow
// DestructiveFileSource::setup_standard_crossfades (frames_per_second);
set_dirty();
/* XXX need to reset/reinstantiate all LADSPA plugins */
@ -1493,7 +1496,7 @@ Session::set_block_size (jack_nframes_t nframes)
(*i)->set_block_size (nframes);
}
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->set_block_size (nframes);
}
@ -1900,14 +1903,14 @@ Session::add_route (Route* route)
}
void
Session::add_diskstream (DiskStream* dstream)
Session::add_diskstream (AudioDiskstream* dstream)
{
/* need to do this in case we're rolling at the time, to prevent false underruns */
dstream->do_refill(0, 0, 0);
{
Glib::RWLock::WriterLock lm (diskstream_lock);
diskstreams.push_back (dstream);
audio_diskstreams.push_back (dstream);
}
/* take a reference to the diskstream, preventing it from
@ -1927,7 +1930,7 @@ Session::add_diskstream (DiskStream* dstream)
set_dirty();
save_state (_current_snapshot_name);
DiskStreamAdded (dstream); /* EMIT SIGNAL */
AudioDiskstreamAdded (dstream); /* EMIT SIGNAL */
}
void
@ -1961,18 +1964,24 @@ Session::remove_route (Route& route)
update_route_solo_state ();
}
{
Glib::RWLock::WriterLock lm (diskstream_lock);
AudioTrack* at;
AudioDiskstream* ds = 0;
if ((at = dynamic_cast<AudioTrack*>(&route)) != 0) {
diskstreams.remove (&at->disk_stream());
at->disk_stream().unref ();
ds = &at->disk_stream();
}
if (ds) {
{
Glib::RWLock::WriterLock lm (diskstream_lock);
audio_diskstreams.remove (ds);
}
ds->unref ();
}
find_current_end ();
}
update_latency_compensation (false, false);
set_dirty();
@ -2255,7 +2264,7 @@ Session::get_maximum_extent () const
ensure atomicity.
*/
for (DiskStreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
Playlist* pl = (*i)->playlist();
if ((me = pl->get_maximum_extent()) > max) {
max = me;
@ -2265,12 +2274,12 @@ Session::get_maximum_extent () const
return max;
}
DiskStream *
AudioDiskstream *
Session::diskstream_by_name (string name)
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->name() == name) {
return* i;
}
@ -2279,12 +2288,12 @@ Session::diskstream_by_name (string name)
return 0;
}
DiskStream *
AudioDiskstream *
Session::diskstream_by_id (id_t id)
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->id() == id) {
return *i;
}
@ -2583,7 +2592,10 @@ Session::destroy_region (Region* region)
for (vector<Source*>::iterator i = srcs.begin(); i != srcs.end(); ++i) {
if ((*i)->use_cnt() == 0) {
(*i)->mark_for_remove ();
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*i);
if (afs) {
(afs)->mark_for_remove ();
}
delete *i;
}
}
@ -2607,7 +2619,7 @@ Session::remove_last_capture ()
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
list<Region*>& l = (*i)->last_capture_regions();
if (!l.empty()) {
@ -2630,15 +2642,15 @@ Session::remove_region_from_region_list (Region& r)
/* Source Management */
void
Session::add_source (Source* source)
Session::add_audio_source (AudioSource* source)
{
pair<SourceList::key_type, SourceList::mapped_type> entry;
pair<AudioSourceList::key_type, AudioSourceList::mapped_type> entry;
{
Glib::Mutex::Lock lm (source_lock);
Glib::Mutex::Lock lm (audio_source_lock);
entry.first = source->id();
entry.second = source;
sources.insert (entry);
audio_sources.insert (entry);
}
source->GoingAway.connect (mem_fun (this, &Session::remove_source));
@ -2650,13 +2662,13 @@ Session::add_source (Source* source)
void
Session::remove_source (Source* source)
{
SourceList::iterator i;
AudioSourceList::iterator i;
{
Glib::Mutex::Lock lm (source_lock);
Glib::Mutex::Lock lm (audio_source_lock);
if ((i = sources.find (source->id())) != sources.end()) {
sources.erase (i);
if ((i = audio_sources.find (source->id())) != audio_sources.end()) {
audio_sources.erase (i);
}
}
@ -2675,15 +2687,21 @@ Session::remove_source (Source* source)
Source *
Session::get_source (ARDOUR::id_t id)
{
Glib::Mutex::Lock lm (source_lock);
SourceList::iterator i;
Glib::Mutex::Lock lm (audio_source_lock);
AudioSourceList::iterator i;
Source* source = 0;
if ((i = sources.find (id)) != sources.end()) {
if ((i = audio_sources.find (id)) != audio_sources.end()) {
source = (*i).second;
}
if (source) {
return source;
}
/* XXX search MIDI or other searches here */
return 0;
}
string
@ -2890,17 +2908,23 @@ Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool
return spath;
}
FileSource *
Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive)
AudioFileSource *
Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
{
string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
/* this might throw failed_constructor(), which is OK */
if (destructive) {
return new DestructiveFileSource (spath, frame_rate(), false, Config->get_native_file_data_format());
return new DestructiveFileSource (spath,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
frame_rate());
} else {
return new FileSource (spath, frame_rate(), false, Config->get_native_file_data_format());
return new SndFileSource (spath,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
frame_rate());
}
}
@ -3082,7 +3106,7 @@ Session::remove_empty_sounds ()
for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
if (FileSource::is_empty (*(*i))) {
if (AudioFileSource::is_empty (*(*i))) {
unlink ((*i)->c_str());
@ -3140,12 +3164,12 @@ Session::set_all_mute (bool yn)
}
uint32_t
Session::n_diskstreams () const
Session::n_audio_diskstreams () const
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
uint32_t n = 0;
for (DiskStreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
n++;
}
@ -3154,10 +3178,10 @@ Session::n_diskstreams () const
}
void
Session::foreach_diskstream (void (DiskStream::*func)(void))
Session::foreach_audio_diskstream (void (AudioDiskstream::*func)(void))
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
((*i)->*func)();
}
@ -3184,7 +3208,7 @@ Session::graph_reordered ()
reflect any changes in latencies within the graph.
*/
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->set_capture_offset ();
}
}
@ -3467,7 +3491,7 @@ Session::reset_native_file_format ()
//RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
Glib::RWLock::ReaderLock lm2 (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->reset_write_sources (false);
}
}
@ -3487,7 +3511,7 @@ Session::route_name_unique (string n) const
}
int
Session::remove_file_source (FileSource& fs)
Session::cleanup_audio_file_source (AudioFileSource& fs)
{
return fs.move_to_trash (dead_sound_dir_name);
}
@ -3562,12 +3586,12 @@ Session::freeze (InterThreadInfo& itt)
}
int
Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_t len, bool overwrite, vector<Source*>& srcs,
InterThreadInfo& itt)
Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nframes_t len,
bool overwrite, vector<AudioSource*>& srcs, InterThreadInfo& itt)
{
int ret = -1;
Playlist* playlist;
FileSource* fsource;
AudioFileSource* fsource;
uint32_t x;
char buf[PATH_MAX+1];
string dir;
@ -3612,7 +3636,11 @@ Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_
}
try {
fsource = new FileSource (buf, frame_rate(), false, Config->get_native_file_data_format());
fsource = new SndFileSource (buf,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
frame_rate());
}
catch (failed_constructor& err) {
@ -3651,11 +3679,15 @@ Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_
}
uint32_t n = 0;
for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
if ((*src)->write (buffers[n], this_chunk, workbuf) != this_chunk) {
for (vector<AudioSource*>::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src);
if (afs) {
if (afs->write (buffers[n], this_chunk, workbuf) != this_chunk) {
goto out;
}
}
}
start += this_chunk;
to_do -= this_chunk;
@ -3671,14 +3703,20 @@ Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_
time (&now);
xnow = localtime (&now);
for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src) {
dynamic_cast<FileSource*>((*src))->update_header (position, *xnow, now);
for (vector<AudioSource*>::iterator src=srcs.begin(); src != srcs.end(); ++src) {
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src);
if (afs) {
afs->update_header (position, *xnow, now);
}
}
/* build peakfile for new source */
for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src) {
dynamic_cast<FileSource*>(*src)->build_peaks ();
for (vector<AudioSource*>::iterator src=srcs.begin(); src != srcs.end(); ++src) {
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src);
if (afs) {
afs->build_peaks ();
}
}
ret = 0;
@ -3686,8 +3724,11 @@ Session::write_one_track (AudioTrack& track, jack_nframes_t start, jack_nframes_
out:
if (ret) {
for (vector<Source*>::iterator src=srcs.begin(); src != srcs.end(); ++src) {
dynamic_cast<FileSource*>(*src)->mark_for_remove ();
for (vector<AudioSource*>::iterator src=srcs.begin(); src != srcs.end(); ++src) {
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*src);
if (afs) {
afs->mark_for_remove ();
}
delete *src;
}
}

View file

@ -34,7 +34,7 @@
#include <ardour/configuration.h>
#include <ardour/audioengine.h>
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/crossfade.h>
#include <ardour/timestamps.h>
@ -168,10 +168,10 @@ Session::butler_thread_work ()
struct timeval begin, end;
struct pollfd pfd[1];
bool disk_work_outstanding = false;
DiskStreamList::iterator i;
AudioDiskstreamList::iterator i;
butler_mixdown_buffer = new Sample[DiskStream::disk_io_frames()];
butler_gain_buffer = new gain_t[DiskStream::disk_io_frames()];
butler_mixdown_buffer = new Sample[AudioDiskstream::disk_io_frames()];
butler_gain_buffer = new gain_t[AudioDiskstream::disk_io_frames()];
// this buffer is used for temp conversion purposes in filesources
char * conv_buffer = conversion_buffer(ButlerContext);
@ -241,7 +241,7 @@ Session::butler_thread_work ()
}
}
for (i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
// cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
}
@ -257,7 +257,7 @@ Session::butler_thread_work ()
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
// cerr << "rah fondr " << (*i)->io()->name () << endl;
@ -278,7 +278,7 @@ Session::butler_thread_work ()
}
if (i != diskstreams.end()) {
if (i != audio_diskstreams.end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
@ -300,7 +300,7 @@ Session::butler_thread_work ()
compute_io = true;
gettimeofday (&begin, 0);
for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) {
// cerr << "write behind for " << (*i)->name () << endl;
@ -330,7 +330,7 @@ Session::butler_thread_work ()
request_stop ();
}
if (i != diskstreams.end()) {
if (i != audio_diskstreams.end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
@ -357,7 +357,7 @@ Session::butler_thread_work ()
Glib::Mutex::Lock lm (butler_request_lock);
if (butler_should_run && (disk_work_outstanding || transport_work_requested())) {
// for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
// for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
// cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
// }
@ -375,7 +375,7 @@ Session::butler_thread_work ()
void
Session::request_overwrite_buffer (DiskStream* stream)
Session::request_overwrite_buffer (AudioDiskstream* stream)
{
Event *ev = new Event (Event::Overwrite, Event::Add, Event::Immediate, 0, 0, 0.0);
ev->set_ptr (stream);
@ -383,7 +383,7 @@ Session::request_overwrite_buffer (DiskStream* stream)
}
void
Session::overwrite_some_buffers (DiskStream* ds)
Session::overwrite_some_buffers (AudioDiskstream* ds)
{
/* executed by the audio thread */
@ -398,7 +398,7 @@ Session::overwrite_some_buffers (DiskStream* ds)
} else {
Glib::RWLock::ReaderLock dm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->set_pending_overwrite (true);
}
}

View file

@ -28,7 +28,7 @@
#include <ardour/ardour.h>
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include "i18n.h"
@ -389,11 +389,11 @@ Session::process_event (Event* ev)
break;
case Event::Overwrite:
overwrite_some_buffers (static_cast<DiskStream*>(ev->ptr));
overwrite_some_buffers (static_cast<AudioDiskstream*>(ev->ptr));
break;
case Event::SetDiskstreamSpeed:
set_diskstream_speed (static_cast<DiskStream*> (ev->ptr), ev->speed);
set_diskstream_speed (static_cast<AudioDiskstream*> (ev->ptr), ev->speed);
break;
case Event::SetSlaveSource:

View file

@ -47,7 +47,7 @@
#include <ardour/sndfile_helpers.h>
#include <ardour/port.h>
#include <ardour/audioengine.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/panner.h>
#include "i18n.h"
@ -495,7 +495,7 @@ Session::prepare_to_export (AudioExportSpecification& spec)
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)-> seek (spec.start_frame, true)) {
error << string_compose (_("%1: cannot seek to %2 for export"),
(*i)->name(), spec.start_frame)

View file

@ -38,7 +38,7 @@
#include <ardour/audioengine.h>
#include <ardour/session.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/control_protocol.h>
#include "i18n.h"

View file

@ -37,7 +37,7 @@
#include <ardour/audioengine.h>
#include <ardour/session.h>
#include <ardour/audio_track.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/slave.h>
#include <ardour/cycles.h>

View file

@ -30,7 +30,7 @@
#include <ardour/ardour.h>
#include <ardour/session.h>
#include <ardour/timestamps.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/audioengine.h>
#include <ardour/slave.h>
#include <ardour/auditioner.h>
@ -64,7 +64,7 @@ Session::process (jack_nframes_t nframes)
void
Session::prepare_diskstreams ()
{
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->prepare ();
}
}
@ -136,12 +136,12 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
if ((ret = (*i)->roll (nframes, _transport_frame, _transport_frame + nframes, offset, declick, record_active, rec_monitors)) < 0) {
/* we have to do this here. Route::roll() for an AudioTrack will have called DiskStream::process(),
and the DS will expect DiskStream::commit() to be called. but we're aborting from that
/* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
call path, so make sure we release any outstanding locks here before we return failure.
*/
for (DiskStreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
(*ids)->recover ();
}
@ -175,12 +175,12 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
if ((ret = (*i)->silent_roll (nframes, _transport_frame, _transport_frame + nframes, offset, record_active, rec_monitors)) < 0) {
/* we have to do this here. Route::roll() for an AudioTrack will have called DiskStream::process(),
and the DS will expect DiskStream::commit() to be called. but we're aborting from that
/* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
call path, so make sure we release any outstanding locks here before we return failure.
*/
for (DiskStreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
(*ids)->recover ();
}
@ -199,7 +199,7 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler)
float pworst = 1.0f;
float cworst = 1.0f;
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->hidden()) {
continue;
@ -566,7 +566,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
bool ok = true;
jack_nframes_t frame_delta = slave_transport_frame - _transport_frame;
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->can_internal_playback_seek (frame_delta)) {
ok = false;
break;
@ -574,7 +574,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
}
if (ok) {
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->internal_playback_seek (frame_delta);
}
_transport_frame += frame_delta;

View file

@ -58,13 +58,11 @@
#include <ardour/audioengine.h>
#include <ardour/configuration.h>
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/utils.h>
#include <ardour/audioplaylist.h>
#include <ardour/source.h>
#include <ardour/filesource.h>
#include <ardour/audiofilesource.h>
#include <ardour/destructive_filesource.h>
#include <ardour/sndfilesource.h>
#include <ardour/sndfile_helpers.h>
#include <ardour/auditioner.h>
#include <ardour/export.h>
@ -196,12 +194,13 @@ Session::first_stage_init (string fullpath, string snapshot_name)
destructive_index = 0;
/* allocate conversion buffers */
_conversion_buffers[ButlerContext] = new char[DiskStream::disk_io_frames() * 4];
_conversion_buffers[TransportContext] = new char[DiskStream::disk_io_frames() * 4];
_conversion_buffers[ButlerContext] = new char[AudioDiskstream::disk_io_frames() * 4];
_conversion_buffers[TransportContext] = new char[AudioDiskstream::disk_io_frames() * 4];
/* default short fade = 15ms */
Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
DestructiveFileSource::setup_standard_crossfades (frame_rate());
last_mmc_step.tv_sec = 0;
last_mmc_step.tv_usec = 0;
@ -267,10 +266,10 @@ Session::first_stage_init (string fullpath, string snapshot_name)
/* These are all static "per-class" signals */
Region::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
Source::SourceCreated.connect (mem_fun (*this, &Session::add_source));
AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source));
Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
DiskStream::DiskStreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
AudioDiskstream::AudioDiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
@ -285,7 +284,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
int
Session::second_stage_init (bool new_session)
{
ExternalSource::set_peak_dir (peak_dir());
AudioFileSource::set_peak_dir (peak_dir());
if (!new_session) {
if (load_state (_current_snapshot_name)) {
@ -425,7 +424,7 @@ Session::setup_raid_path (string path)
}
fspath += tape_dir_name;
FileSource::set_search_path (fspath);
AudioFileSource::set_search_path (fspath);
return;
}
@ -481,9 +480,9 @@ Session::setup_raid_path (string path)
session_dirs.push_back (sp);
}
/* set the FileSource search path */
/* set the AudioFileSource search path */
FileSource::set_search_path (fspath);
AudioFileSource::set_search_path (fspath);
/* reset the round-robin soundfile path thingie */
@ -625,11 +624,11 @@ Session::load_diskstreams (const XMLNode& node)
for (citer = clist.begin(); citer != clist.end(); ++citer) {
DiskStream* dstream;
AudioDiskstream* dstream;
try {
dstream = new DiskStream (*this, **citer);
/* added automatically by DiskStreamCreated handler */
dstream = new AudioDiskstream (*this, **citer);
/* added automatically by AudioDiskstreamCreated handler */
}
catch (failed_constructor& err) {
@ -1335,15 +1334,15 @@ Session::state(bool full_state)
child = node->add_child ("Sources");
if (full_state) {
Glib::Mutex::Lock sl (source_lock);
Glib::Mutex::Lock sl (audio_source_lock);
for (SourceList::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
/* Don't save information about FileSources that are empty */
/* Don't save information about AudioFileSources that are empty */
FileSource* fs;
AudioFileSource* fs;
if ((fs = dynamic_cast<FileSource*> ((*siter).second)) != 0) {
if ((fs = dynamic_cast<AudioFileSource*> ((*siter).second)) != 0) {
DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
/* destructive file sources are OK if they are empty, because
@ -1380,7 +1379,7 @@ Session::state(bool full_state)
{
Glib::RWLock::ReaderLock dl (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
child->add_child_nocopy ((*i)->get_state());
}
@ -1511,7 +1510,7 @@ Session::set_state (const XMLNode& node)
Options
Sources
AudioRegions
DiskStreams
AudioDiskstreams
Connections
Locations
Routes
@ -1745,6 +1744,7 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
const XMLProperty* prop;
id_t s_id;
Source* source;
AudioSource* as;
AudioRegion::SourceList sources;
uint32_t nchans = 1;
char buf[128];
@ -1772,7 +1772,13 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
return 0;
}
sources.push_back(source);
as = dynamic_cast<AudioSource*>(source);
if (!as) {
error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
return 0;
}
sources.push_back (as);
/* pickup other channels */
@ -1785,7 +1791,13 @@ Session::XMLRegionFactory (const XMLNode& node, bool full)
error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
return 0;
}
sources.push_back(source);
as = dynamic_cast<AudioSource*>(source);
if (!as) {
error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
return 0;
}
sources.push_back (as);
}
}
@ -1804,12 +1816,14 @@ Session::get_sources_as_xml ()
{
XMLNode* node = new XMLNode (X_("Sources"));
Glib::Mutex::Lock lm (source_lock);
Glib::Mutex::Lock lm (audio_source_lock);
for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
node->add_child_nocopy ((*i).second->get_state());
}
/* XXX get MIDI and other sources here */
return *node;
}
@ -1867,24 +1881,13 @@ Session::XMLSourceFactory (const XMLNode& node)
}
try {
if (node.property (X_("destructive")) != 0) {
src = new DestructiveFileSource (node, frame_rate());
} else {
src = new FileSource (node, frame_rate());
}
src = AudioFileSource::create (node);
}
catch (failed_constructor& err) {
try {
src = ExternalSource::create (node);
}
catch (failed_constructor& err) {
error << _("Found a sound file that cannot be used by Ardour. See the progammers.") << endmsg;
error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
return 0;
}
}
return src;
}
@ -2930,9 +2933,9 @@ Session::cleanup_sources (Session::cleanup_report& rep)
rep.paths.clear ();
rep.space = 0;
for (SourceList::iterator i = sources.begin(); i != sources.end(); ) {
for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
SourceList::iterator tmp;
AudioSourceList::iterator tmp;
tmp = i;
++tmp;
@ -2949,7 +2952,7 @@ Session::cleanup_sources (Session::cleanup_report& rep)
adding it to the list of all sources below
*/
sources.erase (i);
audio_sources.erase (i);
}
i = tmp;
@ -3019,14 +3022,11 @@ Session::cleanup_sources (Session::cleanup_report& rep)
/* add our current source list
*/
for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
FileSource* fs;
ExternalSource* sfs;
for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
AudioFileSource* fs;
if ((fs = dynamic_cast<FileSource*> ((*i).second)) != 0) {
if ((fs = dynamic_cast<AudioFileSource*> ((*i).second)) != 0) {
all_sources.insert (fs->path());
} else if ((sfs = dynamic_cast<ExternalSource*> ((*i).second)) != 0) {
all_sources.insert (sfs->path());
}
}

View file

@ -32,6 +32,7 @@
#include <ardour/audioengine.h>
#include <ardour/session.h>
#include <ardour/tempo.h>
#include <ardour/audiofilesource.h>
#include "i18n.h"
@ -91,6 +92,9 @@ Session::set_smpte_offset (jack_nframes_t off)
{
_smpte_offset = off;
last_smpte_valid = false;
AudioFileSource::set_header_position_offset (_smpte_offset, _smpte_offset_negative);
SMPTEOffsetChanged (); /* EMIT SIGNAL */
}
@ -99,6 +103,9 @@ Session::set_smpte_offset_negative (bool neg)
{
_smpte_offset_negative = neg;
last_smpte_valid = false;
AudioFileSource::set_header_position_offset (_smpte_offset, _smpte_offset_negative);
SMPTEOffsetChanged (); /* EMIT SIGNAL */
}
@ -690,7 +697,7 @@ Session::smpte_duration_string (char* buf, jack_nframes_t when) const
SMPTE_Time smpte;
smpte_duration (when, smpte);
snprintf (buf, sizeof (buf), "%02ld:%02ld:%02ld:%02ld", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
snprintf (buf, sizeof (buf), "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
}
void

View file

@ -27,7 +27,6 @@
#include <ardour/session.h>
#include <ardour/audioregion.h>
#include <ardour/filesource.h>
#include <ardour/sndfilesource.h>
#include "i18n.h"
@ -80,7 +79,10 @@ Session::tempoize_region (TimeStretchRequest& tsr)
}
try {
sources.push_back(new FileSource (path, frame_rate(), false, Config->get_native_file_data_format()));
sources.push_back (new SndFileSource (path,
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
frame_rate()));
} catch (failed_constructor& err) {
error << string_compose (_("tempoize: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;
goto out;
@ -150,7 +152,10 @@ Session::tempoize_region (TimeStretchRequest& tsr)
xnow = localtime (&now);
for (it = sources.begin(); it != sources.end(); ++it) {
dynamic_cast<FileSource*>(*it)->update_header (tsr.region->position(), *xnow, now);
AudioFileSource* afs = dynamic_cast<AudioFileSource*>(*it);
if (afs) {
afs->update_header (tsr.region->position(), *xnow, now);
}
}
region_name = tsr.region->name() + X_(".t");

View file

@ -36,7 +36,7 @@
#include <ardour/ardour.h>
#include <ardour/audioengine.h>
#include <ardour/session.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/auditioner.h>
#include <ardour/slave.h>
#include <ardour/location.h>
@ -78,7 +78,7 @@ Session::request_transport_speed (float speed)
}
void
Session::request_diskstream_speed (DiskStream& ds, float speed)
Session::request_diskstream_speed (AudioDiskstream& ds, float speed)
{
Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed);
ev->set_ptr (&ds);
@ -200,7 +200,7 @@ Session::butler_transport_work ()
}
if (post_transport_work & PostTransportInputChange) {
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->non_realtime_input_change ();
}
}
@ -216,7 +216,7 @@ Session::butler_transport_work ()
cumulative_rf_motion = 0;
reset_rf_scale (0);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@ -248,7 +248,7 @@ Session::non_realtime_set_speed ()
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->non_realtime_set_speed ();
}
}
@ -258,7 +258,7 @@ Session::non_realtime_overwrite ()
{
Glib::RWLock::ReaderLock lm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->pending_overwrite) {
(*i)->overwrite_existing_buffers ();
}
@ -274,7 +274,7 @@ Session::non_realtime_stop (bool abort)
did_record = false;
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->get_captured_frames () != 0) {
did_record = true;
break;
@ -327,7 +327,7 @@ Session::non_realtime_stop (bool abort)
_have_captured = true;
}
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->transport_stopped (*now, xnow, abort);
}
@ -364,7 +364,7 @@ Session::non_realtime_stop (bool abort)
}
#endif
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@ -491,7 +491,7 @@ Session::set_auto_loop (bool yn)
if (seamless_loop) {
// set all diskstreams to use internal looping
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (loc);
}
@ -499,7 +499,7 @@ Session::set_auto_loop (bool yn)
}
else {
// set all diskstreams to NOT use internal looping
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (0);
}
@ -529,7 +529,7 @@ Session::set_auto_loop (bool yn)
clear_events (Event::AutoLoop);
// set all diskstreams to NOT use internal looping
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (0);
}
@ -645,7 +645,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input);
@ -660,7 +660,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true);
@ -704,7 +704,7 @@ Session::set_transport_speed (float speed, bool abort)
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true);
@ -730,7 +730,7 @@ Session::set_transport_speed (float speed, bool abort)
The rarity and short potential lock duration makes this "OK"
*/
Glib::RWLock::ReaderLock dsm (diskstream_lock);
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
@ -781,7 +781,7 @@ Session::set_transport_speed (float speed, bool abort)
_last_transport_speed = _transport_speed;
_transport_speed = speed;
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
}
@ -871,7 +871,7 @@ Session::actually_start_transport ()
transport_sub_state |= PendingDeclickIn;
_transport_speed = 1.0;
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->realtime_set_speed ((*i)->speed(), true);
}
@ -1001,7 +1001,7 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
_slave_type = src;
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
non_rt_required = true;
@ -1033,7 +1033,7 @@ Session::reverse_diskstream_buffers ()
}
void
Session::set_diskstream_speed (DiskStream* stream, float speed)
Session::set_diskstream_speed (AudioDiskstream* stream, float speed)
{
if (stream->realtime_set_speed (speed, false)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
@ -1229,7 +1229,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
/* reflect any changes in latencies into capture offsets
*/
for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->set_capture_offset ();
}
}

View file

@ -18,47 +18,203 @@
$Id$
*/
#include <cerrno>
#include <climits>
#include <pwd.h>
#include <sys/utsname.h>
#include <glibmm/miscutils.h>
#include <ardour/sndfilesource.h>
#include "i18n.h"
using namespace std;
using namespace ARDOUR;
SndFileSource::SndFileSource (const XMLNode& node)
: ExternalSource (node)
: AudioFileSource (node)
{
init (_name, true);
SourceCreated (this); /* EMIT SIGNAL */
init (_name);
if (open()) {
throw failed_constructor ();
}
if (_build_peakfiles) {
if (initialize_peakfile (false, _path)) {
sf_close (sf);
sf = 0;
throw failed_constructor ();
}
}
AudioSourceCreated (this); /* EMIT SIGNAL */
}
SndFileSource::SndFileSource (const string& idstr, bool build_peak)
: ExternalSource(idstr, build_peak)
SndFileSource::SndFileSource (string idstr, Flag flags)
: AudioFileSource (idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{
init (idstr, build_peak);
init (idstr);
if (build_peak) {
SourceCreated (this); /* EMIT SIGNAL */
if (open()) {
throw failed_constructor ();
}
if (_build_peakfiles) {
if (initialize_peakfile (false, _path)) {
sf_close (sf);
sf = 0;
throw failed_constructor ();
}
}
AudioSourceCreated (this); /* EMIT SIGNAL */
}
SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
: AudioFileSource(idstr, flags, sfmt, hf)
{
int fmt = 0;
init (idstr);
cerr << "creating " << idstr << " hf = " << hf << endl;
switch (hf) {
case CAF:
fmt = SF_FORMAT_CAF;
_flags = Flag (_flags & ~Broadcast);
break;
case AIFF:
fmt = SF_FORMAT_AIFF;
_flags = Flag (_flags & ~Broadcast);
break;
case BWF:
fmt = SF_FORMAT_WAV;
_flags = Flag (_flags | Broadcast);
break;
case WAVE:
fmt = SF_FORMAT_WAV;
_flags = Flag (_flags & ~Broadcast);
break;
case WAVE64:
fmt = SF_FORMAT_W64;
_flags = Flag (_flags & ~Broadcast);
break;
default:
fatal << string_compose (_("programming error: %1"), X_("unsupported audio header format requested")) << endmsg;
/*NOTREACHED*/
break;
}
switch (sfmt) {
case FormatFloat:
fmt |= SF_FORMAT_FLOAT;
break;
case FormatInt24:
fmt |= SF_FORMAT_PCM_24;
break;
}
_info.channels = 1;
_info.samplerate = rate;
_info.format = fmt;
if (open()) {
throw failed_constructor();
}
if (writable() && (_flags & Broadcast)) {
_broadcast_info = new SF_BROADCAST_INFO;
memset (_broadcast_info, 0, sizeof (*_broadcast_info));
snprintf (_broadcast_info->description, sizeof (_broadcast_info->description), "BWF %s", _name.c_str());
struct utsname utsinfo;
if (uname (&utsinfo)) {
error << string_compose(_("FileSource: cannot get host information for BWF header (%1)"), strerror(errno)) << endmsg;
return;
}
snprintf (_broadcast_info->originator, sizeof (_broadcast_info->originator), "ardour:%s:%s:%s:%s:%s)",
Glib::get_real_name().c_str(),
utsinfo.nodename,
utsinfo.sysname,
utsinfo.release,
utsinfo.version);
_broadcast_info->version = 1;
/* XXX do something about this field */
snprintf (_broadcast_info->umid, sizeof (_broadcast_info->umid), "%s", "fnord");
/* coding history is added by libsndfile */
if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (_broadcast_info)) != SF_TRUE) {
char errbuf[256];
sf_error_str (0, errbuf, sizeof (errbuf) - 1);
error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"), _path, errbuf) << endmsg;
_flags = Flag (_flags & ~Broadcast);
delete _broadcast_info;
_broadcast_info = 0;
}
}
if (_build_peakfiles) {
if (initialize_peakfile (false, _path)) {
sf_close (sf);
sf = 0;
throw failed_constructor ();
}
}
/* since SndFileSource's constructed with this constructor can be writable, make sure we update if the header info changes */
if (writable()) {
HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioFileSource::handle_header_position_change));
}
if (_build_peakfiles) {
if (initialize_peakfile (false, _path)) {
sf_close (sf);
sf = 0;
throw failed_constructor ();
}
}
AudioSourceCreated (this); /* EMIT SIGNAL */
}
void
SndFileSource::init (const string& idstr, bool build_peak)
SndFileSource::init (const string& idstr)
{
string::size_type pos;
string file;
tmpbuf = 0;
tmpbufsize = 0;
interleave_buf = 0;
interleave_bufsize = 0;
sf = 0;
_name = idstr;
_broadcast_info = 0;
if ((pos = idstr.find_last_of (':')) == string::npos) {
channel = 0;
file = idstr;
_name = Glib::path_get_basename (idstr);
} else {
channel = atoi (idstr.substr (pos+1).c_str());
file = idstr.substr (0, pos);
_name = Glib::path_get_basename (idstr.substr (0, pos));
}
/* although libsndfile says we don't need to set this,
@ -66,46 +222,56 @@ SndFileSource::init (const string& idstr, bool build_peak)
*/
memset (&_info, 0, sizeof(_info));
}
/* note that we temporarily truncated _id at the colon */
if ((sf = sf_open (file.c_str(), SFM_READ, &_info)) == 0) {
int
SndFileSource::open ()
{
if ((sf = sf_open (_path.c_str(), (writable() ? SFM_RDWR : SFM_READ), &_info)) == 0) {
char errbuf[256];
sf_error_str (0, errbuf, sizeof (errbuf) - 1);
error << string_compose(_("SndFileSource: cannot open file \"%1\" (%2)"), file, errbuf) << endmsg;
throw failed_constructor();
error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"),
_path, (writable() ? "read+write" : "reading"), errbuf) << endmsg;
return -1;
}
if (channel >= _info.channels) {
error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, channel) << endmsg;
sf_close (sf);
sf = 0;
throw failed_constructor();
return -1;
}
_length = _info.frames;
_path = file;
if (build_peak) {
if (initialize_peakfile (false, _path)) {
if (writable()) {
sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
}
return 0;
}
void
SndFileSource::close ()
{
if (sf) {
sf_close (sf);
sf = 0;
throw failed_constructor ();
}
}
}
SndFileSource::~SndFileSource ()
{
GoingAway (this); /* EMIT SIGNAL */
if (sf) {
sf_close (sf);
close ();
if (interleave_buf) {
delete [] interleave_buf;
}
if (tmpbuf) {
delete [] tmpbuf;
if (_broadcast_info) {
delete [] _broadcast_info;
}
}
@ -116,11 +282,33 @@ SndFileSource::sample_rate () const
}
jack_nframes_t
SndFileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
SndFileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
{
int32_t nread;
float *ptr;
uint32_t real_cnt;
jack_nframes_t file_cnt;
if (start > _length) {
/* read starts beyond end of data, just memset to zero */
file_cnt = 0;
} else if (start + cnt > _length) {
/* read ends beyond end of data, read some, memset the rest */
file_cnt = _length - start;
} else {
/* read is entirely within data */
file_cnt = cnt;
}
if (file_cnt) {
if (sf_seek (sf, (off_t) start, SEEK_SET) < 0) {
char errbuf[256];
@ -130,27 +318,30 @@ SndFileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char
}
if (_info.channels == 1) {
jack_nframes_t ret = sf_read_float (sf, dst, cnt);
jack_nframes_t ret = sf_read_float (sf, dst, file_cnt);
_read_data_count = cnt * sizeof(float);
return ret;
}
}
if (file_cnt != cnt) {
jack_nframes_t delta = cnt - file_cnt;
memset (dst+file_cnt, 0, sizeof (Sample) * delta);
}
real_cnt = cnt * _info.channels;
{
Glib::Mutex::Lock lm (_tmpbuf_lock);
if (interleave_bufsize < real_cnt) {
if (tmpbufsize < real_cnt) {
if (tmpbuf) {
delete [] tmpbuf;
if (interleave_buf) {
delete [] interleave_buf;
}
tmpbufsize = real_cnt;
tmpbuf = new float[tmpbufsize];
interleave_bufsize = real_cnt;
interleave_buf = new float[interleave_bufsize];
}
nread = sf_read_float (sf, tmpbuf, real_cnt);
ptr = tmpbuf + channel;
nread = sf_read_float (sf, interleave_buf, real_cnt);
ptr = interleave_buf + channel;
nread /= _info.channels;
/* stride through the interleaved data */
@ -159,10 +350,169 @@ SndFileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char
dst[n] = *ptr;
ptr += _info.channels;
}
}
_read_data_count = cnt * sizeof(float);
return nread;
}
jack_nframes_t
SndFileSource::write_unlocked (Sample *data, jack_nframes_t cnt, char * workbuf)
{
if (!writable()) {
return 0;
}
if (_info.channels != 1) {
fatal << string_compose (_("programming error: %1 %2"), X_("SndFileSource::write called on non-mono file"), _path) << endmsg;
/*NOTREACHED*/
return 0;
}
jack_nframes_t oldlen;
int32_t frame_pos = _length;
if (write_float (data, frame_pos, cnt) != cnt) {
return 0;
}
oldlen = _length;
update_length (oldlen, cnt);
if (_build_peakfiles) {
PeakBuildRecord *pbr = 0;
if (pending_peak_builds.size()) {
pbr = pending_peak_builds.back();
}
if (pbr && pbr->frame + pbr->cnt == oldlen) {
/* the last PBR extended to the start of the current write,
so just extend it again.
*/
pbr->cnt += cnt;
} else {
pending_peak_builds.push_back (new PeakBuildRecord (oldlen, cnt));
}
_peaks_built = false;
}
if (_build_peakfiles) {
queue_for_peaks (*this);
}
_write_data_count = cnt;
return cnt;
}
int
SndFileSource::update_header (jack_nframes_t when, struct tm& now, time_t tnow)
{
/* allow derived classes to override how this is done */
set_timeline_position (when);
if (_flags & Broadcast) {
/* this will flush the header implicitly */
return setup_broadcast_info (when, now, tnow);
} else {
return flush_header ();
}
}
int
SndFileSource::flush_header ()
{
return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
}
int
SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t tnow)
{
/* random code is 9 digits */
int random_code = random() % 999999999;
snprintf (_broadcast_info->originator_reference, sizeof (_broadcast_info->originator_reference), "%2s%3s%12s%02d%02d%02d%9d",
bwf_country_code,
bwf_organization_code,
bwf_serial_number,
now.tm_hour,
now.tm_min,
now.tm_sec,
random_code);
snprintf (_broadcast_info->origination_date, sizeof (_broadcast_info->origination_date), "%4d-%02d-%02d",
1900 + now.tm_year,
now.tm_mon,
now.tm_mday);
snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d-%02d-%02d",
now.tm_hour,
now.tm_min,
now.tm_sec);
/* now update header position taking header offset into account */
set_header_timeline_position ();
/* note that libsndfile flushes the header to disk when resetting the broadcast info */
if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
_flags = Flag (_flags & ~Broadcast);
delete _broadcast_info;
_broadcast_info = 0;
return -1;
}
return 0;
}
void
SndFileSource::set_header_timeline_position ()
{
uint64_t pos;
_broadcast_info->time_reference_high = 0;
if (header_position_negative) {
if (ULONG_LONG_MAX - header_position_offset < timeline_position) {
pos = ULONG_LONG_MAX; // impossible
} else {
pos = timeline_position + header_position_offset;
}
} else {
if (timeline_position < header_position_offset) {
pos = 0;
} else {
pos = timeline_position - header_position_offset;
}
}
_broadcast_info->time_reference_high = (pos >> 32);
_broadcast_info->time_reference_low = (pos & 0xffffffff);
}
jack_nframes_t
SndFileSource::write_float (Sample* data, jack_nframes_t frame_pos, jack_nframes_t cnt)
{
if (sf_seek (sf, frame_pos, SEEK_SET) != frame_pos) {
error << string_compose (_("%1: cannot seek to %2"), _path, frame_pos) << endmsg;
return 0;
}
if (sf_writef_float (sf, data, cnt) != (ssize_t) cnt) {
return 0;
}
return cnt;
}

View file

@ -42,35 +42,18 @@ using std::max;
using namespace ARDOUR;
sigc::signal<void,Source *> Source::SourceCreated;
pthread_t Source::peak_thread;
bool Source::have_peak_thread = false;
vector<Source*> Source::pending_peak_sources;
Glib::StaticMutex Source::pending_peak_sources_lock = GLIBMM_STATIC_MUTEX_INIT;
int Source::peak_request_pipe[2];
bool Source::_build_missing_peakfiles = false;
bool Source::_build_peakfiles = false;
Source::Source (bool announce)
Source::Source (string name)
{
_name = name;
_id = ARDOUR::new_id();
_use_cnt = 0;
_peaks_built = false;
next_peak_clear_should_notify = true;
_timestamp = 0;
_read_data_count = 0;
_write_data_count = 0;
}
Source::Source (const XMLNode& node)
{
_use_cnt = 0;
_peaks_built = false;
next_peak_clear_should_notify = true;
_timestamp = 0;
_read_data_count = 0;
_write_data_count = 0;
if (set_state (node)) {
throw failed_constructor();
@ -96,10 +79,6 @@ Source::get_state ()
node->add_property ("timestamp", buf);
}
if (_captured_for.length()) {
node->add_property ("captured-for", _captured_for);
}
return *node;
}
@ -124,734 +103,9 @@ Source::set_state (const XMLNode& node)
sscanf (prop->value().c_str(), "%ld", &_timestamp);
}
if ((prop = node.property ("captured-for")) != 0) {
_captured_for = prop->value();
}
return 0;
}
/***********************************************************************
PEAK FILE STUFF
***********************************************************************/
void*
Source::peak_thread_work (void* arg)
{
PBD::ThreadCreated (pthread_self(), X_("Peak"));
struct pollfd pfd[1];
Glib::Mutex::Lock lm (pending_peak_sources_lock);
while (true) {
pfd[0].fd = peak_request_pipe[0];
pfd[0].events = POLLIN|POLLERR|POLLHUP;
pending_peak_sources_lock.unlock();
if (poll (pfd, 1, -1) < 0) {
if (errno == EINTR) {
pending_peak_sources_lock.lock();
continue;
}
error << string_compose (_("poll on peak request pipe failed (%1)"),
strerror (errno))
<< endmsg;
break;
}
if (pfd[0].revents & ~POLLIN) {
error << _("Error on peak thread request pipe") << endmsg;
break;
}
if (pfd[0].revents & POLLIN) {
char req;
/* empty the pipe of all current requests */
while (1) {
size_t nread = ::read (peak_request_pipe[0], &req, sizeof (req));
if (nread == 1) {
switch ((PeakRequest::Type) req) {
case PeakRequest::Build:
break;
case PeakRequest::Quit:
pthread_exit_pbd (0);
/*NOTREACHED*/
break;
default:
break;
}
} else if (nread == 0) {
break;
} else if (errno == EAGAIN) {
break;
} else {
fatal << _("Error reading from peak request pipe") << endmsg;
/*NOTREACHED*/
}
}
}
pending_peak_sources_lock.lock();
while (!pending_peak_sources.empty()) {
Source* s = pending_peak_sources.front();
pending_peak_sources.erase (pending_peak_sources.begin());
pending_peak_sources_lock.unlock();
s->build_peaks();
pending_peak_sources_lock.lock();
}
}
pthread_exit_pbd (0);
/*NOTREACHED*/
return 0;
}
int
Source::start_peak_thread ()
{
if (!_build_peakfiles) {
return 0;
}
if (pipe (peak_request_pipe)) {
error << string_compose(_("Cannot create transport request signal pipe (%1)"), strerror (errno)) << endmsg;
return -1;
}
if (fcntl (peak_request_pipe[0], F_SETFL, O_NONBLOCK)) {
error << string_compose(_("UI: cannot set O_NONBLOCK on peak request pipe (%1)"), strerror (errno)) << endmsg;
return -1;
}
if (fcntl (peak_request_pipe[1], F_SETFL, O_NONBLOCK)) {
error << string_compose(_("UI: cannot set O_NONBLOCK on peak request pipe (%1)"), strerror (errno)) << endmsg;
return -1;
}
if (pthread_create_and_store ("peak file builder", &peak_thread, 0, peak_thread_work, 0)) {
error << _("Source: could not create peak thread") << endmsg;
return -1;
}
have_peak_thread = true;
return 0;
}
void
Source::stop_peak_thread ()
{
if (!have_peak_thread) {
return;
}
void* status;
char c = (char) PeakRequest::Quit;
::write (peak_request_pipe[1], &c, 1);
pthread_join (peak_thread, &status);
}
void
Source::queue_for_peaks (Source& source)
{
if (have_peak_thread) {
Glib::Mutex::Lock lm (pending_peak_sources_lock);
source.next_peak_clear_should_notify = true;
if (find (pending_peak_sources.begin(),
pending_peak_sources.end(),
&source) == pending_peak_sources.end()) {
pending_peak_sources.push_back (&source);
}
char c = (char) PeakRequest::Build;
::write (peak_request_pipe[1], &c, 1);
}
}
void Source::clear_queue_for_peaks ()
{
/* this is done to cancel a group of running peak builds */
if (have_peak_thread) {
Glib::Mutex::Lock lm (pending_peak_sources_lock);
pending_peak_sources.clear ();
}
}
bool
Source::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
{
bool ret;
Glib::Mutex::Lock lm (_lock);
/* check to see if the peak data is ready. if not
connect the slot while still holding the lock.
*/
if (!(ret = _peaks_built)) {
conn = PeaksReady.connect (the_slot);
}
return ret;
}
int
Source::rename_peakfile (string newpath)
{
/* caller must hold _lock */
string oldpath = peakpath;
if (access (oldpath.c_str(), F_OK) == 0) {
if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
return -1;
}
}
peakpath = newpath;
return 0;
}
int
Source::initialize_peakfile (bool newfile, string audio_path)
{
struct stat statbuf;
peakpath = peak_path (audio_path);
if (newfile) {
if (!_build_peakfiles) {
return 0;
}
_peaks_built = false;
} else {
if (stat (peakpath.c_str(), &statbuf)) {
if (errno != ENOENT) {
/* it exists in the peaks dir, but there is some kind of error */
error << string_compose(_("Source: cannot stat peakfile \"%1\""), peakpath) << endmsg;
return -1;
}
} else {
/* we found it in the peaks dir */
}
if (statbuf.st_size == 0) {
_peaks_built = false;
} else {
// Check if the audio file has changed since the peakfile was built.
struct stat stat_file;
int err = stat (audio_path.c_str(), &stat_file);
if (!err && stat_file.st_mtime > statbuf.st_mtime){
_peaks_built = false;
} else {
_peaks_built = true;
}
}
}
if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
build_peaks_from_scratch ();
}
return 0;
}
int
Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start, jack_nframes_t cnt, double samples_per_visual_peak) const
{
Glib::Mutex::Lock lm (_lock);
double scale;
double expected_peaks;
PeakData::PeakDatum xmax;
PeakData::PeakDatum xmin;
int32_t to_read;
uint32_t nread;
jack_nframes_t zero_fill = 0;
int ret = -1;
PeakData* staging = 0;
Sample* raw_staging = 0;
char * workbuf = 0;
int peakfile = -1;
expected_peaks = (cnt / (double) frames_per_peak);
scale = npeaks/expected_peaks;
#if 0
cerr << "======>RP: npeaks = " << npeaks
<< " start = " << start
<< " cnt = " << cnt
<< " len = " << _length
<< " samples_per_visual_peak =" << samples_per_visual_peak
<< " expected was " << expected_peaks << " ... scale = " << scale
<< " PD ptr = " << peaks
<<endl;
#endif
/* fix for near-end-of-file conditions */
if (cnt > _length - start) {
// cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << endl;
cnt = _length - start;
jack_nframes_t old = npeaks;
npeaks = min ((jack_nframes_t) floor (cnt / samples_per_visual_peak), npeaks);
zero_fill = old - npeaks;
}
// cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
if (npeaks == cnt) {
// cerr << "RAW DATA\n";
/* no scaling at all, just get the sample data and duplicate it for
both max and min peak values.
*/
Sample* raw_staging = new Sample[cnt];
workbuf = new char[cnt*4];
if (read_unlocked (raw_staging, start, cnt, workbuf) != cnt) {
error << _("cannot read sample data for unscaled peak computation") << endmsg;
return -1;
}
for (jack_nframes_t i = 0; i < npeaks; ++i) {
peaks[i].max = raw_staging[i];
peaks[i].min = raw_staging[i];
}
delete [] raw_staging;
delete [] workbuf;
return 0;
}
if (scale == 1.0) {
off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
/* open, read, close */
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
// cerr << "DIRECT PEAKS\n";
nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
close (peakfile);
if (nread != sizeof (PeakData) * npeaks) {
cerr << "Source["
<< _name
<< "]: cannot read peaks from peakfile! (read only "
<< nread
<< " not "
<< npeaks
<< "at sample "
<< start
<< " = byte "
<< first_peak_byte
<< ')'
<< endl;
return -1;
}
if (zero_fill) {
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
}
return 0;
}
jack_nframes_t tnp;
if (scale < 1.0) {
// cerr << "DOWNSAMPLE\n";
/* the caller wants:
- more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
- less peaks than the peakfile holds for the same range
So, read a block into a staging area, and then downsample from there.
to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks
*/
const uint32_t chunksize = (uint32_t) min (expected_peaks, 4096.0);
staging = new PeakData[chunksize];
/* compute the rounded up frame position */
jack_nframes_t current_frame = start;
jack_nframes_t current_stored_peak = (jack_nframes_t) ceil (current_frame / (double) frames_per_peak);
uint32_t next_visual_peak = (uint32_t) ceil (current_frame / samples_per_visual_peak);
double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
uint32_t stored_peak_before_next_visual_peak = (jack_nframes_t) next_visual_peak_frame / frames_per_peak;
uint32_t nvisual_peaks = 0;
uint32_t stored_peaks_read = 0;
uint32_t i = 0;
/* handle the case where the initial visual peak is on a pixel boundary */
current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
/* open ... close during out: handling */
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return 0;
}
while (nvisual_peaks < npeaks) {
if (i == stored_peaks_read) {
uint32_t start_byte = current_stored_peak * sizeof(PeakData);
tnp = min ((_length/frames_per_peak - current_stored_peak), (jack_nframes_t) expected_peaks);
to_read = min (chunksize, tnp);
off_t fend = lseek (peakfile, 0, SEEK_END);
if ((nread = ::pread (peakfile, staging, sizeof (PeakData) * to_read, start_byte))
!= sizeof (PeakData) * to_read) {
cerr << "Source["
<< _name
<< "]: cannot read peak data from peakfile ("
<< (nread / sizeof(PeakData))
<< " peaks instead of "
<< to_read
<< ") ("
<< strerror (errno)
<< ')'
<< " at start_byte = " << start_byte
<< " _length = " << _length << " versus len = " << fend
<< " expected maxpeaks = " << (_length - current_frame)/frames_per_peak
<< " npeaks was " << npeaks
<< endl;
goto out;
}
i = 0;
stored_peaks_read = nread / sizeof(PeakData);
}
xmax = -1.0;
xmin = 1.0;
while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
xmax = max (xmax, staging[i].max);
xmin = min (xmin, staging[i].min);
++i;
++current_stored_peak;
--expected_peaks;
}
peaks[nvisual_peaks].max = xmax;
peaks[nvisual_peaks].min = xmin;
++nvisual_peaks;
++next_visual_peak;
//next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
next_visual_peak_frame = min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / frames_per_peak;
}
if (zero_fill) {
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
}
ret = 0;
} else {
// cerr << "UPSAMPLE\n";
/* the caller wants
- less frames-per-peak (more resolution)
- more peaks than stored in the Peakfile
So, fetch data from the raw source, and generate peak
data on the fly.
*/
jack_nframes_t frames_read = 0;
jack_nframes_t current_frame = start;
jack_nframes_t i = 0;
jack_nframes_t nvisual_peaks = 0;
jack_nframes_t chunksize = (jack_nframes_t) min (cnt, (jack_nframes_t) 4096);
raw_staging = new Sample[chunksize];
workbuf = new char[chunksize *4];
jack_nframes_t frame_pos = start;
double pixel_pos = floor (frame_pos / samples_per_visual_peak);
double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
double pixels_per_frame = 1.0 / samples_per_visual_peak;
xmin = 1.0;
xmax = -1.0;
while (nvisual_peaks < npeaks) {
if (i == frames_read) {
to_read = min (chunksize, (_length - current_frame));
if ((frames_read = read_unlocked (raw_staging, current_frame, to_read, workbuf)) < 0) {
error << string_compose(_("Source[%1]: peak read - cannot read %2 samples at offset %3")
, _name, to_read, current_frame)
<< endmsg;
goto out;
}
i = 0;
}
xmax = max (xmax, raw_staging[i]);
xmin = min (xmin, raw_staging[i]);
++i;
++current_frame;
pixel_pos += pixels_per_frame;
if (pixel_pos >= next_pixel_pos) {
peaks[nvisual_peaks].max = xmax;
peaks[nvisual_peaks].min = xmin;
++nvisual_peaks;
xmin = 1.0;
xmax = -1.0;
next_pixel_pos = ceil (pixel_pos + 0.5);
}
}
if (zero_fill) {
memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
}
ret = 0;
}
out:
if (peakfile >= 0) {
close (peakfile);
}
if (staging) {
delete [] staging;
}
if (raw_staging) {
delete [] raw_staging;
}
if (workbuf) {
delete [] workbuf;
}
return ret;
}
#undef DEBUG_PEAK_BUILD
int
Source::build_peaks ()
{
vector<PeakBuildRecord*> built;
int status = -1;
bool pr_signal = false;
list<PeakBuildRecord*> copy;
{
Glib::Mutex::Lock lm (_lock);
copy = pending_peak_builds;
pending_peak_builds.clear ();
}
#ifdef DEBUG_PEAK_BUILD
cerr << "build peaks with " << copy.size() << " requests pending\n";
#endif
for (list<PeakBuildRecord *>::iterator i = copy.begin(); i != copy.end(); ++i) {
if ((status = do_build_peak ((*i)->frame, (*i)->cnt)) != 0) {
unlink (peakpath.c_str());
break;
}
built.push_back (new PeakBuildRecord (*(*i)));
delete *i;
}
{
Glib::Mutex::Lock lm (_lock);
if (status == 0) {
_peaks_built = true;
if (next_peak_clear_should_notify) {
next_peak_clear_should_notify = false;
pr_signal = true;
}
}
}
if (status == 0) {
for (vector<PeakBuildRecord *>::iterator i = built.begin(); i != built.end(); ++i) {
PeakRangeReady ((*i)->frame, (*i)->cnt); /* EMIT SIGNAL */
delete *i;
}
if (pr_signal) {
PeaksReady (); /* EMIT SIGNAL */
}
}
return status;
}
int
Source::do_build_peak (jack_nframes_t first_frame, jack_nframes_t cnt)
{
jack_nframes_t current_frame;
Sample buf[frames_per_peak];
Sample xmin, xmax;
uint32_t peaki;
PeakData* peakbuf;
char * workbuf = 0;
jack_nframes_t frames_read;
jack_nframes_t frames_to_read;
off_t first_peak_byte;
int peakfile = -1;
int ret = -1;
#ifdef DEBUG_PEAK_BUILD
cerr << pthread_self() << ": " << _name << ": building peaks for " << first_frame << " to " << first_frame + cnt - 1 << endl;
#endif
first_peak_byte = (first_frame / frames_per_peak) * sizeof (PeakData);
#ifdef DEBUG_PEAK_BUILD
cerr << "seeking to " << first_peak_byte << " before writing new peak data\n";
#endif
current_frame = first_frame;
peakbuf = new PeakData[(cnt/frames_per_peak)+1];
peaki = 0;
workbuf = new char[max(frames_per_peak, cnt) * 4];
if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
while (cnt) {
frames_to_read = min (frames_per_peak, cnt);
if ((frames_read = read_unlocked (buf, current_frame, frames_to_read, workbuf)) != frames_to_read) {
error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
goto out;
}
xmin = buf[0];
xmax = buf[0];
for (jack_nframes_t n = 1; n < frames_read; ++n) {
xmax = max (xmax, buf[n]);
xmin = min (xmin, buf[n]);
// if (current_frame < frames_read) {
// cerr << "sample = " << buf[n] << " max = " << xmax << " min = " << xmin << " max of 2 = " << max (xmax, buf[n]) << endl;
// }
}
peakbuf[peaki].max = xmax;
peakbuf[peaki].min = xmin;
peaki++;
current_frame += frames_read;
cnt -= frames_read;
}
if (::pwrite (peakfile, peakbuf, sizeof (PeakData) * peaki, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaki)) {
error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
goto out;
}
ret = 0;
out:
delete [] peakbuf;
if (peakfile >= 0) {
close (peakfile);
}
if (workbuf)
delete [] workbuf;
return ret;
}
void
Source::build_peaks_from_scratch ()
{
Glib::Mutex::Lock lp (_lock);
next_peak_clear_should_notify = true;
pending_peak_builds.push_back (new PeakBuildRecord (0, _length));
queue_for_peaks (*this);
}
bool
Source::file_changed (string path)
{
struct stat stat_file;
struct stat stat_peak;
int e1 = stat (path.c_str(), &stat_file);
int e2 = stat (peak_path(path).c_str(), &stat_peak);
if (!e1 && !e2 && stat_file.st_mtime > stat_peak.st_mtime){
return true;
} else {
return false;
}
}
void
Source::use ()
{
@ -864,30 +118,3 @@ Source::release ()
if (_use_cnt) --_use_cnt;
}
jack_nframes_t
Source::available_peaks (double zoom_factor) const
{
int peakfile;
off_t end;
if (zoom_factor < frames_per_peak) {
return length(); // peak data will come from the audio file
}
/* peak data comes from peakfile */
if ((peakfile = ::open (peakpath.c_str(), O_RDONLY)) < 0) {
error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return 0;
}
{
Glib::Mutex::Lock lm (_lock);
end = lseek (peakfile, 0, SEEK_END);
}
close (peakfile);
return (end/sizeof(PeakData)) * frames_per_peak;
}