Merged with trunk revision 600

git-svn-id: svn://localhost/ardour2/branches/midi@601 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2006-06-15 01:34:54 +00:00
parent a8f44b1556
commit b5db1f624d
205 changed files with 70728 additions and 2113 deletions

View file

@ -1,3 +1,3 @@
Last merged with trunk revision:
579
600

View file

@ -353,8 +353,8 @@ libraries = { }
libraries['core'] = LibraryInfo (CCFLAGS = '-Ilibs')
libraries['sndfile'] = LibraryInfo()
libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
#libraries['sndfile'] = LibraryInfo()
#libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
libraries['lrdf'] = LibraryInfo()
libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
@ -425,6 +425,15 @@ else:
libraries['usb'] = conf.Finish ()
#
# Check for FLAC
libraries['flac'] = LibraryInfo ()
conf = Configure (libraries['flac'])
conf.CheckLib ('FLAC', 'FLAC__stream_decoder_new')
libraries['flac'] = conf.Finish ()
#
# Check for liblo
@ -504,6 +513,14 @@ if env['SYSLIBS']:
libraries['libgnomecanvasmm'] = LibraryInfo()
libraries['libgnomecanvasmm'].ParseConfig ('pkg-config --cflags --libs libgnomecanvasmm-2.6')
#
# cannot use system one for the time being
#
libraries['sndfile'] = LibraryInfo(LIBS='libsndfile',
LIBPATH='#libs/libsndfile',
CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
# libraries['libglademm'] = LibraryInfo()
# libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
@ -516,6 +533,7 @@ if env['SYSLIBS']:
]
subdirs = [
'libs/libsndfile',
'libs/pbd3',
'libs/midi++2',
'libs/ardour'
@ -553,6 +571,9 @@ else:
libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
LIBPATH='#libs/soundtouch',
CPPPATH=['#libs', '#libs/soundtouch'])
libraries['sndfile'] = LibraryInfo(LIBS='libsndfile',
LIBPATH='#libs/libsndfile',
CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
# libraries['libglademm'] = LibraryInfo(LIBS='libglademm',
# LIBPATH='#libs/libglademm',
# CPPPATH='#libs/libglademm')
@ -565,6 +586,7 @@ else:
subdirs = [
# 'libs/cassowary',
'libs/sigc++2',
'libs/libsndfile',
'libs/pbd3',
'libs/midi++2',
'libs/ardour'

View file

@ -35,6 +35,7 @@ gtkardour.Merge ([
libraries['libgnomecanvasmm'],
libraries['sysmidi'],
libraries['sndfile'],
libraries['flac'],
libraries['lrdf'],
libraries['glibmm2'],
libraries['pangomm'],

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

@ -46,7 +46,7 @@ ARDOUR_UI::setup_config_options ()
struct {
char* name;
bool (Configuration::*method)(void) const;
char act_type; // (t)oggle or (r)adio
char act_type; //(t)oggle or (r)adio
} options[] = {
{ "ToggleTimeMaster", &Configuration::get_jack_time_master, 't' },
{ "StopPluginsWithTransport", &Configuration::get_plugins_stop_with_transport, 't' },
@ -76,7 +76,6 @@ ARDOUR_UI::setup_config_options ()
Glib::RefPtr<Action> act = ActionManager::get_action (i->c_str(), options[n].name);
if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
cerr << "action = " << (options[n].name) << " val = " << (Config->*(options[n].method))() << endl;//DEBUG
if (options[n].act_type == 't' || (options[n].act_type == 'r' && (Config->*(options[n].method))()))
tact->set_active ((Config->*(options[n].method))());
continue;
@ -257,7 +256,6 @@ ARDOUR_UI::toggle_UseHardwareMonitoring()
Glib::RefPtr<Action> act = ActionManager::get_action ("options", "UseHardwareMonitoring");
if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
cerr << "get_active() cond = " << tact->get_active() << endl;//DEBUG
if (tact->get_active()) {
Config->set_use_hardware_monitoring (true);
Config->set_use_sw_monitoring (false);

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

@ -1,37 +0,0 @@
/*
Copyright (C) 2005 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#include <iostream>
#include "glade_factory.h"
Glib::RefPtr<Gnome::Glade::Xml>
GladeFactory::create(const std::string& full_path_to_file,
const Glib::ustring& toplevel_widget)
{
try {
return Gnome::Glade::Xml::create(full_path_to_file,
toplevel_widget,
PACKAGE );
} catch(const Gnome::Glade::XmlError& ex) {
std::cerr << ex.what() << std::endl;
throw ex;
}
}

View file

@ -1,45 +0,0 @@
/*
Copyright (C) 2005 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
// -*- c++ -*-
#ifndef GLADE_FACTORY_H
#define GLADE_FACTORY_H
#include <string>
#include <libglademm/xml.h>
typedef Glib::RefPtr<Gnome::Glade::Xml> GladeRef;
/**
This is the base class for all glade
factories so that the same domain is
used.
*/
class GladeFactory {
protected:
static GladeRef
create(const std::string& full_path,
const Glib::ustring& toplevel_widget = Glib::ustring());
};
#endif // GLADE_FACTORY_H

View file

@ -1,38 +0,0 @@
/*
Copyright (C) 2005 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
#include <ardour/ardour.h>
#include "i18n.h"
#include "glade_path.h"
#include <iostream>
std::string
GladePath::path(const std::string& glade_file)
{
std::string full_path;
full_path = ARDOUR::find_data_file(glade_file, "glade");
return full_path;
}

View file

@ -1,49 +0,0 @@
/*
Copyright (C) 2005 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#ifndef GLADE_PATH_H
#define GLADE_PATH_H
#include <string>
struct GladePath {
/**
@return Path to glade file.
XXX subject to change upon discussion.
glade files are currently looked for in
three possible directories in this order.
In the directory defined in the environment
variable ARDOUR_GLADE_PATH
In the users .ardour/glade directory.
In the system defined glade path.
*/
static std::string
path(const std::string& glade_filename);
};
#endif // GLADE_PATH_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"
@ -69,7 +69,7 @@ class SoundFileBox : public Gtk::VBox
LabelModelColumns label_columns;
ARDOUR::SoundFileInfo sf_info;
ARDOUR::SoundFileInfo sf_info;
pid_t current_pid;

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
@ -202,8 +202,8 @@ ardour.Merge ([
libraries['pbd3'],
libraries['soundtouch'],
libraries['midi++2'],
libraries['glib2'],
libraries['glibmm2']
libraries['glib2'],
libraries['glibmm2']
])
if ardour['LIBLO']:

View file

@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
$Id: diskstream.h 579 2006-06-12 19:56:37Z essej $
*/
#ifndef __ardour_diskstream_h__
@ -52,10 +52,10 @@ class AudioEngine;
class Send;
class Session;
class AudioPlaylist;
class FileSource;
class AudioFileSource;
class IO;
class DiskStream : public Stateful, public sigc::trackable
class AudioDiskstream : public Stateful, public sigc::trackable
{
public:
enum Flag {
@ -64,15 +64,15 @@ class DiskStream : public Stateful, public sigc::trackable
Destructive = 0x4
};
DiskStream (Session &, const string& name, Flag f = Recordable);
DiskStream (Session &, const XMLNode&);
AudioDiskstream (Session &, const string& name, Flag f = Recordable);
AudioDiskstream (Session &, const XMLNode&);
string name() const { return _name; }
ARDOUR::IO* io() const { return _io; }
void set_io (ARDOUR::IO& io);
DiskStream& ref() { _refcnt++; return *this; }
AudioDiskstream& ref() { _refcnt++; return *this; }
void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
uint32_t refcnt() const { return _refcnt; }
@ -154,7 +154,7 @@ class DiskStream : public Stateful, public sigc::trackable
AudioPlaylist *playlist () { return _playlist; }
FileSource *write_source (uint32_t n=0) {
AudioFileSource *write_source (uint32_t n=0) {
if (n < channels.size())
return channels[n].write_source;
return 0;
@ -184,8 +184,8 @@ class DiskStream : public Stateful, public sigc::trackable
static sigc::signal<void> DiskOverrun;
static sigc::signal<void> DiskUnderrun;
static sigc::signal<void,DiskStream*> DiskStreamCreated; // XXX use a ref with sigc2
static sigc::signal<void,list<Source*>*> DeleteSources;
static sigc::signal<void,AudioDiskstream*> AudioDiskstreamCreated; // XXX use a ref with sigc2
static sigc::signal<void,list<AudioFileSource*>*> DeleteSources;
/* stateful */
@ -266,7 +266,7 @@ class DiskStream : public Stateful, public sigc::trackable
/* use unref() to destroy a diskstream */
~DiskStream();
~AudioDiskstream();
enum TransitionType {
CaptureStart = 0,
@ -288,8 +288,8 @@ class DiskStream : public Stateful, public sigc::trackable
float peak_power;
FileSource *fades_source;
FileSource *write_source;
AudioFileSource *fades_source;
AudioFileSource *write_source;
Port *source;
Sample *current_capture_buffer;
@ -432,7 +432,7 @@ class DiskStream : public Stateful, public sigc::trackable
void non_realtime_set_speed ();
std::list<Region*> _last_capture_regions;
std::vector<FileSource*> capturing_sources;
std::vector<AudioFileSource*> capturing_sources;
int use_pending_capture_data (XMLNode& node);
void get_input_sources ();

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

@ -0,0 +1,157 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ardour_audiofilesource_h__
#define __ardour_audiofilesource_h__
#include <time.h>
#include <ardour/audiosource.h>
namespace ARDOUR {
struct SoundFileInfo {
float samplerate;
uint16_t channels;
int64_t length;
std::string format_name;
};
class AudioFileSource : public AudioSource {
public:
enum Flag {
Writable = 0x1,
CanRename = 0x2,
Broadcast = 0x4,
Removable = 0x8,
RemovableIfEmpty = 0x10,
RemoveAtDestroy = 0x20,
BuildPeaks = 0x40
};
virtual ~AudioFileSource ();
int set_name (string newname, bool destructive);
string path() const { return _path; }
string peak_path (string audio_path);
string old_peak_path (string audio_path);
static void set_peak_dir (string dir) { peak_dir = dir; }
/* factory for an existing but not-used-in-session audio file. this exists
because there maybe multiple back-end derivations of AudioFileSource,
some of which can handle formats that cannot be handled by others.
For example, CoreAudioFileSource can handle MP3 files, which SndFileSource
cannot.
*/
static AudioFileSource* create (string path_plus_channel);
static AudioFileSource* create (const XMLNode&);
static bool get_soundfile_info (string path, SoundFileInfo& _info, string& error);
void set_allow_remove_if_empty (bool yn);
void mark_for_remove();
/* this block of methods do nothing for regular file sources, but are significant
for files used in destructive recording.
*/
virtual jack_nframes_t last_capture_start_frame() const { return 0; }
virtual void mark_capture_start (jack_nframes_t) {}
virtual void mark_capture_end () {}
virtual void clear_capture_marks() {}
virtual int update_header (jack_nframes_t when, struct tm&, time_t) = 0;
virtual int flush_header () = 0;
int move_to_trash (const string trash_dir_name);
static bool is_empty (string path);
void mark_streaming_write_completed ();
void mark_take (string);
string take_id() const { return _take_id; }
static void set_bwf_country_code (string x);
static void set_bwf_organization_code (string x);
static void set_bwf_serial_number (int);
static void set_search_path (string);
static void set_header_position_offset (jack_nframes_t offset, bool negative);
static sigc::signal<void,struct tm*, time_t> HeaderPositionOffsetChanged;
XMLNode& get_state ();
int set_state (const XMLNode&);
/* this should really be protected, but C++ is getting stricter
and creating slots from protected member functions is starting
to cause issues.
*/
void handle_header_position_change (struct tm*, time_t tnow);
protected:
/* constructor to be called for existing external-to-session files */
AudioFileSource (std::string path, Flag flags);
/* constructor to be called for new in-session files */
AudioFileSource (std::string path, Flag flags,
SampleFormat samp_format, HeaderFormat hdr_format);
/* constructor to be called for existing in-session files */
AudioFileSource (const XMLNode&);
int init (string idstr, bool must_exist);
uint16_t channel;
string _path;
Flag _flags;
string _take_id;
bool allow_remove_if_empty;
uint64_t timeline_position;
static string peak_dir;
static string search_path;
static char bwf_country_code[3];
static char bwf_organization_code[4];
static char bwf_serial_number[13];
static uint64_t header_position_offset;
static bool header_position_negative;
virtual void set_timeline_position (jack_nframes_t pos);
virtual void set_header_timeline_position () = 0;
bool find (std::string path, bool must_exist, bool& is_new);
bool removable() const;
bool writable() const { return _flags & Writable; }
};
}; /* namespace ARDOUR */
#endif /* __ardour_audiofilesource_h__ */

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

@ -0,0 +1,166 @@
/*
Copyright (C) 2000 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: audio_source.h 486 2006-04-27 09:04:24Z pauld $
*/
#ifndef __ardour_audio_source_h__
#define __ardour_audio_source_h__
#include <list>
#include <vector>
#include <string>
#include <time.h>
#include <glibmm/thread.h>
#include <sigc++/signal.h>
#include <ardour/source.h>
#include <ardour/ardour.h>
#include <ardour/stateful.h>
#include <pbd/xml++.h>
using std::list;
using std::vector;
using std::string;
namespace ARDOUR {
const jack_nframes_t frames_per_peak = 256;
class AudioSource : public Source
{
public:
AudioSource (string name);
AudioSource (const XMLNode&);
virtual ~AudioSource ();
/* returns the number of items in this `audio_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;
virtual jack_nframes_t write (Sample *src, jack_nframes_t cnt, char * workbuf);
virtual float sample_rate () const = 0;
virtual void mark_for_remove() = 0;
virtual void mark_streaming_write_completed () {}
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,AudioSource*> AudioSourceCreated;
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;
}
protected:
static bool _build_missing_peakfiles;
static bool _build_peakfiles;
bool _peaks_built;
mutable Glib::Mutex _lock;
jack_nframes_t _length;
bool next_peak_clear_should_notify;
string peakpath;
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 jack_nframes_t write_unlocked (Sample *dst, jack_nframes_t cnt, char * workbuf) = 0;
virtual string peak_path(string audio_path) = 0;
virtual string old_peak_path(string audio_path) = 0;
void update_length (jack_nframes_t pos, jack_nframes_t cnt);
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<AudioSource*> pending_peak_sources;
static Glib::Mutex* pending_peak_sources_lock;
static void queue_for_peaks (AudioSource&);
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<AudioSource::PeakBuildRecord *> pending_peak_builds;
private:
bool file_changed (string path);
};
}
#endif /* __ardour_audio_source_h__ */

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

@ -1,67 +0,0 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __external_source_h__
#define __external_source_h__
#include <ardour/source.h>
namespace ARDOUR {
struct SoundFileInfo {
float samplerate;
uint16_t channels;
int64_t length;
std::string format_name;
};
class ExternalSource : public Source {
public:
virtual ~ExternalSource ();
string path() const { return _path; }
virtual jack_nframes_t read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const = 0;
void mark_for_remove() {} // we never remove external sndfiles
string peak_path(string audio_path);
string old_peak_path(string audio_path);
static void set_peak_dir (string dir) { peak_dir = dir; }
static ExternalSource* create (const string& path_plus_channel, bool build_peak = true);
static ExternalSource* create (const XMLNode& node);
static bool get_soundfile_info (string path, SoundFileInfo& _info, string& error);
protected:
ExternalSource (const string& path_plus_channel, bool build_peak = true);
ExternalSource (const XMLNode&);
static string peak_dir;
uint16_t channel;
string _path;
jack_nframes_t read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const;
};
}; /* namespace ARDOUR */
#endif /* __external_source_h__ */

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

@ -62,11 +62,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;
@ -263,25 +264,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;
@ -346,7 +352,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);
@ -358,15 +364,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&);
@ -603,7 +609,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);
@ -659,8 +665,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;
@ -692,7 +699,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 */
@ -736,8 +744,8 @@ 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*>&,
InterThreadInfo& wot);
int write_one_audio_track (AudioTrack&, jack_nframes_t start, jack_nframes_t cnt, bool overwrite, vector<AudioSource*>&,
InterThreadInfo& wot);
int freeze (InterThreadInfo&);
/* session-wide solo/mute/rec-enable */
@ -963,7 +971,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();
@ -1422,12 +1430,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 ();
@ -1458,10 +1466,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 */
@ -1503,16 +1511,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 */
@ -1531,7 +1537,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;
uint32_t _use_cnt;
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

@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
$Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
*/
#include <fstream>
@ -38,10 +38,10 @@
#include <ardour/ardour.h>
#include <ardour/audioengine.h>
#include <ardour/diskstream.h>
#include <ardour/audio_diskstream.h>
#include <ardour/utils.h>
#include <ardour/configuration.h>
#include <ardour/filesource.h>
#include <ardour/audiofilesource.h>
#include <ardour/destructive_filesource.h>
#include <ardour/send.h>
#include <ardour/audioplaylist.h>
@ -54,14 +54,14 @@
using namespace std;
using namespace ARDOUR;
jack_nframes_t DiskStream::disk_io_chunk_frames;
jack_nframes_t AudioDiskstream::disk_io_chunk_frames;
sigc::signal<void,DiskStream*> DiskStream::DiskStreamCreated;
sigc::signal<void,list<Source*>*> DiskStream::DeleteSources;
sigc::signal<void> DiskStream::DiskOverrun;
sigc::signal<void> DiskStream::DiskUnderrun;
sigc::signal<void,AudioDiskstream*> AudioDiskstream::AudioDiskstreamCreated;
sigc::signal<void,list<AudioFileSource*>*> AudioDiskstream::DeleteSources;
sigc::signal<void> AudioDiskstream::DiskOverrun;
sigc::signal<void> AudioDiskstream::DiskUnderrun;
DiskStream::DiskStream (Session &sess, const string &name, Flag flag)
AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Flag flag)
: _name (name),
_session (sess)
{
@ -74,10 +74,10 @@ DiskStream::DiskStream (Session &sess, const string &name, Flag flag)
in_set_state = false;
DiskStreamCreated (this); /* EMIT SIGNAL */
AudioDiskstreamCreated (this); /* EMIT SIGNAL */
}
DiskStream::DiskStream (Session& sess, const XMLNode& node)
AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
: _session (sess)
{
@ -95,11 +95,11 @@ DiskStream::DiskStream (Session& sess, const XMLNode& node)
use_destructive_playlist ();
}
DiskStreamCreated (this); /* EMIT SIGNAL */
AudioDiskstreamCreated (this); /* EMIT SIGNAL */
}
void
DiskStream::init_channel (ChannelInfo &chan)
AudioDiskstream::init_channel (ChannelInfo &chan)
{
chan.playback_wrap_buffer = 0;
chan.capture_wrap_buffer = 0;
@ -128,7 +128,7 @@ DiskStream::init_channel (ChannelInfo &chan)
void
DiskStream::init (Flag f)
AudioDiskstream::init (Flag f)
{
_id = new_id();
_refcnt = 0;
@ -185,7 +185,7 @@ DiskStream::init (Flag f)
}
void
DiskStream::destroy_channel (ChannelInfo &chan)
AudioDiskstream::destroy_channel (ChannelInfo &chan)
{
if (chan.write_source) {
chan.write_source->release ();
@ -211,7 +211,7 @@ DiskStream::destroy_channel (ChannelInfo &chan)
chan.capture_buf = 0;
}
DiskStream::~DiskStream ()
AudioDiskstream::~AudioDiskstream ()
{
Glib::Mutex::Lock lm (state_lock);
@ -227,7 +227,7 @@ DiskStream::~DiskStream ()
}
void
DiskStream::handle_input_change (IOChange change, void *src)
AudioDiskstream::handle_input_change (IOChange change, void *src)
{
Glib::Mutex::Lock lm (state_lock);
@ -238,7 +238,7 @@ DiskStream::handle_input_change (IOChange change, void *src)
}
void
DiskStream::non_realtime_input_change ()
AudioDiskstream::non_realtime_input_change ()
{
{
Glib::Mutex::Lock lm (state_lock);
@ -299,7 +299,7 @@ DiskStream::non_realtime_input_change ()
}
void
DiskStream::get_input_sources ()
AudioDiskstream::get_input_sources ()
{
uint32_t ni = _io->n_inputs();
@ -327,18 +327,18 @@ DiskStream::get_input_sources ()
}
int
DiskStream::find_and_use_playlist (const string& name)
AudioDiskstream::find_and_use_playlist (const string& name)
{
Playlist* pl;
AudioPlaylist* playlist;
if ((pl = _session.get_playlist (name)) == 0) {
error << string_compose(_("DiskStream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg;
error << string_compose(_("AudioDiskstream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg;
return -1;
}
if ((playlist = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
error << string_compose(_("DiskStream: Playlist \"%1\" isn't an audio playlist"), name) << endmsg;
error << string_compose(_("AudioDiskstream: Playlist \"%1\" isn't an audio playlist"), name) << endmsg;
return -1;
}
@ -346,7 +346,7 @@ DiskStream::find_and_use_playlist (const string& name)
}
int
DiskStream::use_playlist (AudioPlaylist* playlist)
AudioDiskstream::use_playlist (AudioPlaylist* playlist)
{
{
Glib::Mutex::Lock lm (state_lock);
@ -370,9 +370,9 @@ DiskStream::use_playlist (AudioPlaylist* playlist)
reset_write_sources (false);
}
plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &DiskStream::playlist_changed));
plmod_connection = _playlist->Modified.connect (mem_fun (*this, &DiskStream::playlist_modified));
plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &DiskStream::playlist_deleted));
plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &AudioDiskstream::playlist_changed));
plmod_connection = _playlist->Modified.connect (mem_fun (*this, &AudioDiskstream::playlist_modified));
plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &AudioDiskstream::playlist_deleted));
}
if (!overwrite_queued) {
@ -387,7 +387,7 @@ DiskStream::use_playlist (AudioPlaylist* playlist)
}
void
DiskStream::playlist_deleted (Playlist* pl)
AudioDiskstream::playlist_deleted (Playlist* pl)
{
/* this catches an ordering issue with session destruction. playlists
are destroyed before diskstreams. we have to invalidate any handles
@ -398,7 +398,7 @@ DiskStream::playlist_deleted (Playlist* pl)
}
int
DiskStream::use_new_playlist ()
AudioDiskstream::use_new_playlist ()
{
string newname;
AudioPlaylist* playlist;
@ -422,14 +422,14 @@ DiskStream::use_new_playlist ()
}
int
DiskStream::use_copy_playlist ()
AudioDiskstream::use_copy_playlist ()
{
if (destructive()) {
return 0;
}
if (_playlist == 0) {
error << string_compose(_("DiskStream %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
error << string_compose(_("AudioDiskstream %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
return -1;
}
@ -447,7 +447,7 @@ DiskStream::use_copy_playlist ()
}
void
DiskStream::setup_destructive_playlist ()
AudioDiskstream::setup_destructive_playlist ()
{
AudioRegion::SourceList srcs;
@ -462,7 +462,7 @@ DiskStream::setup_destructive_playlist ()
}
void
DiskStream::use_destructive_playlist ()
AudioDiskstream::use_destructive_playlist ()
{
/* use the sources associated with the single full-extent region */
@ -485,7 +485,7 @@ DiskStream::use_destructive_playlist ()
ChannelList::iterator chan;
for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
(*chan).write_source = dynamic_cast<FileSource*>(&region->source (n));
(*chan).write_source = dynamic_cast<AudioFileSource*>(&region->source (n));
(*chan).write_source->set_allow_remove_if_empty (false);
}
@ -493,14 +493,14 @@ DiskStream::use_destructive_playlist ()
}
void
DiskStream::set_io (IO& io)
AudioDiskstream::set_io (IO& io)
{
_io = &io;
set_align_style_from_io ();
}
int
DiskStream::set_name (string str, void *src)
AudioDiskstream::set_name (string str, void *src)
{
if (str != _name) {
_playlist->set_name (str);
@ -518,7 +518,7 @@ DiskStream::set_name (string str, void *src)
}
void
DiskStream::set_speed (double sp)
AudioDiskstream::set_speed (double sp)
{
_session.request_diskstream_speed (*this, sp);
@ -527,7 +527,7 @@ DiskStream::set_speed (double sp)
}
bool
DiskStream::realtime_set_speed (double sp, bool global)
AudioDiskstream::realtime_set_speed (double sp, bool global)
{
bool changed = false;
double new_speed = sp * _session.transport_speed();
@ -561,7 +561,7 @@ DiskStream::realtime_set_speed (double sp, bool global)
}
void
DiskStream::non_realtime_set_speed ()
AudioDiskstream::non_realtime_set_speed ()
{
if (_buffer_reallocation_required)
{
@ -584,14 +584,14 @@ DiskStream::non_realtime_set_speed ()
}
void
DiskStream::prepare ()
AudioDiskstream::prepare ()
{
_processed = false;
playback_distance = 0;
}
void
DiskStream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
AudioDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
{
int possibly_recording;
int rolling;
@ -716,7 +716,7 @@ DiskStream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t
}
int
DiskStream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input)
AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input)
{
uint32_t n;
ChannelList::iterator c;
@ -731,7 +731,7 @@ DiskStream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jac
just return. this allows multiple routes that are taking input
from this diskstream to call our ::process() method, but have
this stuff only happen once. more commonly, it allows both
the AudioTrack that is using this DiskStream *and* the Session
the AudioTrack that is using this AudioDiskstream *and* the Session
to call process() without problems.
*/
@ -748,7 +748,7 @@ DiskStream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jac
return 0;
}
/* This lock is held until the end of DiskStream::commit, so these two functions
/* This lock is held until the end of AudioDiskstream::commit, so these two functions
must always be called as a pair. The only exception is if this function
returns a non-zero value, in which case, ::commit should not be called.
*/
@ -1010,14 +1010,14 @@ DiskStream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jac
}
void
DiskStream::recover ()
AudioDiskstream::recover ()
{
state_lock.unlock();
_processed = false;
}
bool
DiskStream::commit (jack_nframes_t nframes)
AudioDiskstream::commit (jack_nframes_t nframes)
{
bool need_butler = false;
@ -1056,7 +1056,7 @@ DiskStream::commit (jack_nframes_t nframes)
}
void
DiskStream::set_pending_overwrite (bool yn)
AudioDiskstream::set_pending_overwrite (bool yn)
{
/* called from audio thread, so we can use the read ptr and playback sample as we wish */
@ -1067,7 +1067,7 @@ DiskStream::set_pending_overwrite (bool yn)
}
int
DiskStream::overwrite_existing_buffers ()
AudioDiskstream::overwrite_existing_buffers ()
{
Sample* mixdown_buffer;
float* gain_buffer;
@ -1110,7 +1110,7 @@ DiskStream::overwrite_existing_buffers ()
if (read ((*chan).playback_buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, workbuf,
start, to_read, *chan, n, reversed)) {
error << string_compose(_("DiskStream %1: when refilling, cannot read %2 from playlist at frame %3"),
error << string_compose(_("AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"),
_id, size, playback_sample) << endmsg;
goto out;
}
@ -1121,7 +1121,7 @@ DiskStream::overwrite_existing_buffers ()
if (read ((*chan).playback_buf->buffer(), mixdown_buffer, gain_buffer, workbuf,
start, cnt, *chan, n, reversed)) {
error << string_compose(_("DiskStream %1: when refilling, cannot read %2 from playlist at frame %3"),
error << string_compose(_("AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"),
_id, size, playback_sample) << endmsg;
goto out;
}
@ -1139,7 +1139,7 @@ DiskStream::overwrite_existing_buffers ()
}
int
DiskStream::seek (jack_nframes_t frame, bool complete_refill)
AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill)
{
Glib::Mutex::Lock lm (state_lock);
uint32_t n;
@ -1149,9 +1149,6 @@ DiskStream::seek (jack_nframes_t frame, bool complete_refill)
for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
(*chan).playback_buf->reset ();
(*chan).capture_buf->reset ();
if ((*chan).write_source) {
(*chan).write_source->seek (frame);
}
}
playback_sample = frame;
@ -1167,7 +1164,7 @@ DiskStream::seek (jack_nframes_t frame, bool complete_refill)
}
int
DiskStream::can_internal_playback_seek (jack_nframes_t distance)
AudioDiskstream::can_internal_playback_seek (jack_nframes_t distance)
{
ChannelList::iterator chan;
@ -1180,7 +1177,7 @@ DiskStream::can_internal_playback_seek (jack_nframes_t distance)
}
int
DiskStream::internal_playback_seek (jack_nframes_t distance)
AudioDiskstream::internal_playback_seek (jack_nframes_t distance)
{
ChannelList::iterator chan;
@ -1195,7 +1192,7 @@ DiskStream::internal_playback_seek (jack_nframes_t distance)
}
int
DiskStream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt,
AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt,
ChannelInfo& channel_info, int channel, bool reversed)
{
jack_nframes_t this_read = 0;
@ -1253,7 +1250,7 @@ DiskStream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char
this_read = min(cnt,this_read);
if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
error << string_compose(_("DiskStream %1: cannot read %2 from playlist at frame %3"), _id, this_read,
error << string_compose(_("AudioDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read,
start) << endmsg;
return -1;
}
@ -1286,7 +1283,7 @@ DiskStream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char
}
int
DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
{
int32_t ret = 0;
jack_nframes_t to_read;
@ -1516,7 +1513,7 @@ DiskStream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbu
}
int
DiskStream::do_flush (char * workbuf, bool force_flush)
AudioDiskstream::do_flush (char * workbuf, bool force_flush)
{
uint32_t to_write;
int32_t ret = 0;
@ -1620,7 +1617,7 @@ DiskStream::do_flush (char * workbuf, bool force_flush)
}
if ((!(*chan).write_source) || (*chan).write_source->write (vector.buf[0], to_write, workbuf) != to_write) {
error << string_compose(_("DiskStream %1: cannot write to disk"), _id) << endmsg;
error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
return -1;
}
@ -1637,7 +1634,7 @@ DiskStream::do_flush (char * workbuf, bool force_flush)
to_write = min ((jack_nframes_t)(disk_io_chunk_frames - to_write), (jack_nframes_t) vector.len[1]);
if ((*chan).write_source->write (vector.buf[1], to_write, workbuf) != to_write) {
error << string_compose(_("DiskStream %1: cannot write to disk"), _id) << endmsg;
error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
return -1;
}
@ -1653,13 +1650,13 @@ DiskStream::do_flush (char * workbuf, bool force_flush)
}
void
DiskStream::playlist_changed (Change ignored)
AudioDiskstream::playlist_changed (Change ignored)
{
playlist_modified ();
}
void
DiskStream::playlist_modified ()
AudioDiskstream::playlist_modified ()
{
if (!i_am_the_modifier && !overwrite_queued) {
_session.request_overwrite_buffer (this);
@ -1668,7 +1665,7 @@ DiskStream::playlist_modified ()
}
void
DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
{
uint32_t buffer_position;
bool more_work = true;
@ -1680,7 +1677,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
ChannelList::iterator chan;
vector<CaptureInfo*>::iterator ci;
uint32_t n = 0;
list<Source*>* deletion_list;
list<AudioFileSource*>* deletion_list;
bool mark_write_completed = false;
finish_capture (true);
@ -1697,7 +1694,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
case 1:
break;
case -1:
error << string_compose(_("DiskStream \"%1\": cannot flush captured data to disk!"), _name) << endmsg;
error << string_compose(_("AudioDiskstream \"%1\": cannot flush captured data to disk!"), _name) << endmsg;
err++;
}
}
@ -1713,7 +1710,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
ChannelList::iterator chan;
deletion_list = new list<Source*>;
deletion_list = new list<AudioFileSource*>;
for ( chan = channels.begin(); chan != channels.end(); ++chan) {
@ -1747,15 +1744,15 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
Source* s = (*chan).write_source;
AudioFileSource* s = (*chan).write_source;
if (s) {
FileSource* fsrc;
AudioFileSource* fsrc;
srcs.push_back (s);
if ((fsrc = dynamic_cast<FileSource *>(s)) != 0) {
if ((fsrc = dynamic_cast<AudioFileSource *>(s)) != 0) {
fsrc->update_header (capture_info.front()->start, when, twhen);
}
@ -1817,7 +1814,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
}
catch (failed_constructor& err) {
error << _("DiskStream: could not create region for captured audio!") << endmsg;
error << _("AudioDiskstream: could not create region for captured audio!") << endmsg;
continue; /* XXX is this OK? */
}
@ -1850,7 +1847,7 @@ DiskStream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture
}
void
DiskStream::finish_capture (bool rec_monitors_input)
AudioDiskstream::finish_capture (bool rec_monitors_input)
{
was_recording = false;
@ -1899,7 +1896,7 @@ DiskStream::finish_capture (bool rec_monitors_input)
}
void
DiskStream::set_record_enabled (bool yn, void* src)
AudioDiskstream::set_record_enabled (bool yn, void* src)
{
bool rolling = _session.transport_speed() != 0.0f;
@ -1958,9 +1955,9 @@ DiskStream::set_record_enabled (bool yn, void* src)
}
XMLNode&
DiskStream::get_state ()
AudioDiskstream::get_state ()
{
XMLNode* node = new XMLNode ("DiskStream");
XMLNode* node = new XMLNode ("AudioDiskstream");
char buf[64];
LocaleGuard lg (X_("POSIX"));
@ -1984,7 +1981,7 @@ DiskStream::get_state ()
XMLNode* cs_child = new XMLNode (X_("CapturingSources"));
XMLNode* cs_grandchild;
for (vector<FileSource*>::iterator i = capturing_sources.begin(); i != capturing_sources.end(); ++i) {
for (vector<AudioFileSource*>::iterator i = capturing_sources.begin(); i != capturing_sources.end(); ++i) {
cs_grandchild = new XMLNode (X_("file"));
cs_grandchild->add_property (X_("path"), (*i)->path());
cs_child->add_child_nocopy (*cs_grandchild);
@ -2012,7 +2009,7 @@ DiskStream::get_state ()
}
int
DiskStream::set_state (const XMLNode& node)
AudioDiskstream::set_state (const XMLNode& node)
{
const XMLProperty* prop;
XMLNodeList nlist = node.children();
@ -2137,14 +2134,14 @@ DiskStream::set_state (const XMLNode& node)
}
int
DiskStream::use_new_write_source (uint32_t n)
AudioDiskstream::use_new_write_source (uint32_t n)
{
if (!recordable()) {
return 1;
}
if (n >= channels.size()) {
error << string_compose (_("DiskStream: channel %1 out of range"), n) << endmsg;
error << string_compose (_("AudioDiskstream: channel %1 out of range"), n) << endmsg;
return -1;
}
@ -2152,7 +2149,7 @@ DiskStream::use_new_write_source (uint32_t n)
if (chan.write_source) {
if (FileSource::is_empty (chan.write_source->path())) {
if (AudioFileSource::is_empty (chan.write_source->path())) {
chan.write_source->mark_for_remove ();
chan.write_source->release();
delete chan.write_source;
@ -2163,7 +2160,7 @@ DiskStream::use_new_write_source (uint32_t n)
}
try {
if ((chan.write_source = _session.create_file_source (*this, n, destructive())) == 0) {
if ((chan.write_source = _session.create_audio_source_for_session (*this, n, destructive())) == 0) {
throw failed_constructor();
}
}
@ -2184,7 +2181,7 @@ DiskStream::use_new_write_source (uint32_t n)
}
void
DiskStream::reset_write_sources (bool mark_write_complete, bool force)
AudioDiskstream::reset_write_sources (bool mark_write_complete, bool force)
{
ChannelList::iterator chan;
uint32_t n;
@ -2227,7 +2224,7 @@ DiskStream::reset_write_sources (bool mark_write_complete, bool force)
}
int
DiskStream::rename_write_sources ()
AudioDiskstream::rename_write_sources ()
{
ChannelList::iterator chan;
uint32_t n;
@ -2243,7 +2240,7 @@ DiskStream::rename_write_sources ()
}
void
DiskStream::set_block_size (jack_nframes_t nframes)
AudioDiskstream::set_block_size (jack_nframes_t nframes)
{
if (_session.get_block_size() > speed_buffer_size) {
speed_buffer_size = _session.get_block_size();
@ -2257,7 +2254,7 @@ DiskStream::set_block_size (jack_nframes_t nframes)
}
void
DiskStream::allocate_temporary_buffers ()
AudioDiskstream::allocate_temporary_buffers ()
{
/* make sure the wrap buffer is at least large enough to deal
with the speeds up to 1.2, to allow for micro-variation
@ -2281,7 +2278,7 @@ DiskStream::allocate_temporary_buffers ()
}
void
DiskStream::monitor_input (bool yn)
AudioDiskstream::monitor_input (bool yn)
{
for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
@ -2292,7 +2289,7 @@ DiskStream::monitor_input (bool yn)
}
void
DiskStream::set_capture_offset ()
AudioDiskstream::set_capture_offset ()
{
if (_io == 0) {
/* can't capture, so forget it */
@ -2303,13 +2300,13 @@ DiskStream::set_capture_offset ()
}
void
DiskStream::set_persistent_align_style (AlignStyle a)
AudioDiskstream::set_persistent_align_style (AlignStyle a)
{
_persistent_alignment_style = a;
}
void
DiskStream::set_align_style_from_io ()
AudioDiskstream::set_align_style_from_io ()
{
bool have_physical = false;
@ -2334,7 +2331,7 @@ DiskStream::set_align_style_from_io ()
}
void
DiskStream::set_align_style (AlignStyle a)
AudioDiskstream::set_align_style (AlignStyle a)
{
if (record_enabled() && _session.actively_recording()) {
return;
@ -2348,7 +2345,7 @@ DiskStream::set_align_style (AlignStyle a)
}
int
DiskStream::add_channel ()
AudioDiskstream::add_channel ()
{
/* XXX need to take lock??? */
@ -2368,7 +2365,7 @@ DiskStream::add_channel ()
}
int
DiskStream::remove_channel ()
AudioDiskstream::remove_channel ()
{
if (channels.size() > 1) {
/* XXX need to take lock??? */
@ -2384,21 +2381,21 @@ DiskStream::remove_channel ()
}
float
DiskStream::playback_buffer_load () const
AudioDiskstream::playback_buffer_load () const
{
return (float) ((double) channels.front().playback_buf->read_space()/
(double) channels.front().playback_buf->bufsize());
}
float
DiskStream::capture_buffer_load () const
AudioDiskstream::capture_buffer_load () const
{
return (float) ((double) channels.front().capture_buf->write_space()/
(double) channels.front().capture_buf->bufsize());
}
int
DiskStream::set_loop (Location *location)
AudioDiskstream::set_loop (Location *location)
{
if (location) {
if (location->start() >= location->end()) {
@ -2414,7 +2411,7 @@ DiskStream::set_loop (Location *location)
}
jack_nframes_t
DiskStream::get_capture_start_frame (uint32_t n)
AudioDiskstream::get_capture_start_frame (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
@ -2427,7 +2424,7 @@ DiskStream::get_capture_start_frame (uint32_t n)
}
jack_nframes_t
DiskStream::get_captured_frames (uint32_t n)
AudioDiskstream::get_captured_frames (uint32_t n)
{
Glib::Mutex::Lock lm (capture_info_lock);
@ -2440,23 +2437,23 @@ DiskStream::get_captured_frames (uint32_t n)
}
void
DiskStream::punch_in ()
AudioDiskstream::punch_in ()
{
}
void
DiskStream::punch_out ()
AudioDiskstream::punch_out ()
{
}
int
DiskStream::use_pending_capture_data (XMLNode& node)
AudioDiskstream::use_pending_capture_data (XMLNode& node)
{
const XMLProperty* prop;
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
FileSource* fs;
FileSource* first_fs = 0;
AudioFileSource* fs;
AudioFileSource* first_fs = 0;
AudioRegion::SourceList pending_sources;
jack_nframes_t position;
@ -2476,7 +2473,10 @@ DiskStream::use_pending_capture_data (XMLNode& node)
}
try {
fs = new FileSource (prop->value(), _session.frame_rate(), true, Config->get_native_file_data_format());
fs = new SndFileSource (prop->value(),
Config->get_native_file_data_format(),
Config->get_native_file_header_format(),
_session.frame_rate());
}
catch (failed_constructor& err) {
@ -2543,13 +2543,13 @@ DiskStream::use_pending_capture_data (XMLNode& node)
}
void
DiskStream::set_roll_delay (jack_nframes_t nframes)
AudioDiskstream::set_roll_delay (jack_nframes_t nframes)
{
_roll_delay = nframes;
}
void
DiskStream::set_destructive (bool yn)
AudioDiskstream::set_destructive (bool yn)
{
if (yn != destructive()) {
reset_write_sources (true, true);

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

@ -0,0 +1,661 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <vector>
#include <sys/time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <pbd/mountpoint.h>
#include <pbd/pathscanner.h>
#include <pbd/stl_delete.h>
#include <pbd/strsplit.h>
#include <sndfile.h>
#include <glibmm/miscutils.h>
#include <ardour/audiofilesource.h>
#include <ardour/sndfile_helpers.h>
#include <ardour/sndfilesource.h>
#include <ardour/destructive_filesource.h>
#include <ardour/session.h>
// if these headers come before sigc++ is included
// the parser throws ObjC++ errors. (nil is a keyword)
#ifdef HAVE_COREAUDIO
#include <ardour/coreaudio_source.h>
#include <AudioToolbox/ExtendedAudioFile.h>
#include <AudioToolbox/AudioFormat.h>
#endif // HAVE_COREAUDIO
#include "i18n.h"
using namespace ARDOUR;
string AudioFileSource::peak_dir = "";
string AudioFileSource::search_path;
sigc::signal<void,struct tm*, time_t> AudioFileSource::HeaderPositionOffsetChanged;
bool AudioFileSource::header_position_negative;
uint64_t AudioFileSource::header_position_offset;
char AudioFileSource::bwf_country_code[3] = "US";
char AudioFileSource::bwf_organization_code[4] = "LAS";
char AudioFileSource::bwf_serial_number[13] = "000000000000";
AudioFileSource::AudioFileSource (string idstr, Flag flags)
: AudioSource (idstr), _flags (flags)
{
/* constructor used for existing external to session files. file must exist already */
if (init (idstr, true)) {
throw failed_constructor ();
}
}
AudioFileSource::AudioFileSource (std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
: AudioSource (path), _flags (flags)
{
/* constructor used for new internal-to-session files. file cannot exist */
if (init (path, false)) {
throw failed_constructor ();
}
}
AudioFileSource::AudioFileSource (const XMLNode& node)
: AudioSource (node), _flags (Flag (Writable|CanRename))
{
/* constructor used for existing internal-to-session files. file must exist */
if (set_state (node)) {
throw failed_constructor ();
}
if (init (_name, true)) {
throw failed_constructor ();
}
}
AudioFileSource::~AudioFileSource ()
{
if (removable()) {
unlink (_path.c_str());
unlink (peakpath.c_str());
}
}
bool
AudioFileSource::removable () const
{
return (_flags & Removable) && ((_flags & RemoveAtDestroy) ||
((_flags & RemovableIfEmpty) && is_empty (_path)));
}
int
AudioFileSource::init (string pathstr, bool must_exist)
{
bool is_new = false;
_length = 0;
next_peak_clear_should_notify = false;
if (!find (pathstr, must_exist, is_new)) {
cerr << "cannot find " << pathstr << " with me = " << must_exist << endl;
return -1;
}
if (is_new && must_exist) {
return -1;
}
return 0;
}
string
AudioFileSource::peak_path (string audio_path)
{
return Session::peak_path_from_audio_path (audio_path);
}
string
AudioFileSource::old_peak_path (string audio_path)
{
/* XXX hardly bombproof! fix me */
struct stat stat_file;
struct stat stat_mount;
string mp = mountpoint (audio_path);
stat (audio_path.c_str(), &stat_file);
stat (mp.c_str(), &stat_mount);
char buf[32];
#ifdef __APPLE__
snprintf (buf, sizeof (buf), "%u-%u-%d.peak", stat_mount.st_ino, stat_file.st_ino, channel);
#else
snprintf (buf, sizeof (buf), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, channel);
#endif
string res = peak_dir;
res += buf;
return res;
}
#ifdef HAVE_COREAUDIO
AudioFileSource*
AudioFileSource::create (const XMLNode& node)
{
AudioFileSource* es = 0;
if (node.property (X_("destructive")) != 0) {
es = new DestructiveFileSource (node);
} else {
try {
es = new CoreAudioSource (node);
}
catch (failed_constructor& err) {
es = new SndFileSource (node);
}
}
return es;
}
#else
AudioFileSource*
AudioFileSource::create (const XMLNode& node)
{
if (node.property (X_("destructive")) != 0) {
return new DestructiveFileSource (node);
} else {
return new SndFileSource (node);
}
}
#endif // HAVE_COREAUDIO
#ifdef HAVE_COREAUDIO
AudioFileSource*
AudioFileSource::create (const string& idstr)
{
AudioFileSource* es = 0;
try {
es = new CoreAudioSource (idstr);
}
catch (failed_constructor& err) {
es = new SndFileSource (idstr);
}
return es;
}
#else
AudioFileSource*
AudioFileSource::create (string idstr)
{
return new SndFileSource (idstr);
}
#endif // HAVE_COREAUDIO
#ifdef HAVE_COREAUDIO
std::string
CFStringRefToStdString(CFStringRef stringRef)
{
CFIndex size =
CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef) ,
kCFStringEncodingASCII);
char *buf = new char[size];
std::string result;
if(CFStringGetCString(stringRef, buf, size, kCFStringEncodingASCII)) {
result = buf;
}
delete [] buf;
return result;
}
#endif // HAVE_COREAUDIO
bool
AudioFileSource::get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg)
{
#ifdef HAVE_COREAUDIO
OSStatus err = noErr;
FSRef ref;
ExtAudioFileRef af = 0;
size_t size;
CFStringRef name;
err = FSPathMakeRef ((UInt8*)path.c_str(), &ref, 0);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
err = ExtAudioFileOpen(&ref, &af);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
AudioStreamBasicDescription absd;
memset(&absd, 0, sizeof(absd));
size = sizeof(AudioStreamBasicDescription);
err = ExtAudioFileGetProperty(af,
kExtAudioFileProperty_FileDataFormat, &size, &absd);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
_info.samplerate = absd.mSampleRate;
_info.channels = absd.mChannelsPerFrame;
size = sizeof(_info.length);
err = ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &size, &_info.length);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
size = sizeof(CFStringRef);
err = AudioFormatGetProperty(
kAudioFormatProperty_FormatName, sizeof(absd), &absd, &size, &name);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
_info.format_name = CFStringRefToStdString(name);
ExtAudioFileDispose (af);
return true;
libsndfile:
#endif // HAVE_COREAUDIO
SNDFILE *sf;
SF_INFO sf_info;
sf_info.format = 0; // libsndfile says to clear this before sf_open().
if ((sf = sf_open ((char*) path.c_str(), SFM_READ, &sf_info)) == 0) {
char errbuf[256];
error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1);
return false;
}
sf_close (sf);
_info.samplerate = sf_info.samplerate;
_info.channels = sf_info.channels;
_info.length = sf_info.frames;
_info.format_name = string_compose("Format: %1, %2",
sndfile_major_format(sf_info.format),
sndfile_minor_format(sf_info.format));
return true;
}
XMLNode&
AudioFileSource::get_state ()
{
XMLNode& root (AudioSource::get_state());
char buf[16];
snprintf (buf, sizeof (buf), "0x%x", (int)_flags);
root.add_property ("flags", buf);
return root;
}
int
AudioFileSource::set_state (const XMLNode& node)
{
const XMLProperty* prop;
if (AudioSource::set_state (node)) {
return -1;
}
if ((prop = node.property (X_("flags"))) != 0) {
int ival;
sscanf (prop->value().c_str(), "0x%x", &ival);
_flags = Flag (ival);
} else {
_flags = Flag (0);
}
return 0;
}
void
AudioFileSource::mark_for_remove ()
{
if (!writable()) {
return;
}
_flags = Flag (_flags | RemoveAtDestroy);
}
void
AudioFileSource::mark_streaming_write_completed ()
{
if (!writable()) {
return;
}
Glib::Mutex::Lock lm (_lock);
next_peak_clear_should_notify = true;
if (_peaks_built || pending_peak_builds.empty()) {
_peaks_built = true;
PeaksReady (); /* EMIT SIGNAL */
}
}
void
AudioFileSource::mark_take (string id)
{
if (writable()) {
_take_id = id;
}
}
int
AudioFileSource::move_to_trash (const string trash_dir_name)
{
string newpath;
if (!writable()) {
return -1;
}
/* don't move the file across filesystems, just
stick it in the `trash_dir_name' directory
on whichever filesystem it was already on.
*/
newpath = Glib::path_get_dirname (_path);
newpath = Glib::path_get_dirname (newpath);
newpath += '/';
newpath += trash_dir_name;
newpath += '/';
newpath += Glib::path_get_basename (_path);
if (access (newpath.c_str(), F_OK) == 0) {
/* the new path already exists, try versioning */
char buf[PATH_MAX+1];
int version = 1;
string newpath_v;
snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
newpath_v = buf;
while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
newpath_v = buf;
}
if (version == 999) {
error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
newpath)
<< endmsg;
} else {
newpath = newpath_v;
}
} else {
/* it doesn't exist, or we can't read it or something */
}
if (::rename (_path.c_str(), newpath.c_str()) != 0) {
error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
_path, newpath, strerror (errno))
<< endmsg;
return -1;
}
if (::unlink (peakpath.c_str()) != 0) {
error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
peakpath, _path, strerror (errno))
<< endmsg;
/* try to back out */
rename (newpath.c_str(), _path.c_str());
return -1;
}
_path = newpath;
peakpath = "";
/* file can not be removed twice, since the operation is not idempotent */
_flags = Flag (_flags & ~(RemoveAtDestroy|Removable|RemovableIfEmpty));
return 0;
}
bool
AudioFileSource::find (string pathstr, bool must_exist, bool& isnew)
{
string::size_type pos;
bool ret = false;
isnew = false;
/* clean up PATH:CHANNEL notation so that we are looking for the correct path */
if ((pos = pathstr.find_last_of (':')) == string::npos) {
pathstr = pathstr;
} else {
pathstr = pathstr.substr (0, pos);
}
if (pathstr[0] != '/') {
/* non-absolute pathname: find pathstr in search path */
vector<string> dirs;
int cnt;
string fullpath;
string keeppath;
if (search_path.length() == 0) {
error << _("FileSource: search path not set") << endmsg;
goto out;
}
split (search_path, dirs, ':');
cnt = 0;
for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
fullpath = *i;
if (fullpath[fullpath.length()-1] != '/') {
fullpath += '/';
}
fullpath += pathstr;
if (access (fullpath.c_str(), R_OK) == 0) {
keeppath = fullpath;
++cnt;
}
}
if (cnt > 1) {
error << string_compose (_("FileSource: \"%1\" is ambigous when searching %2\n\t"), pathstr, search_path) << endmsg;
goto out;
} else if (cnt == 0) {
if (must_exist) {
error << string_compose(_("Filesource: cannot find required file (%1): while searching %2"), pathstr, search_path) << endmsg;
goto out;
} else {
isnew = true;
}
}
_name = pathstr;
_path = keeppath;
ret = true;
} else {
/* external files and/or very very old style sessions include full paths */
_path = pathstr;
_name = pathstr.substr (pathstr.find_last_of ('/') + 1);
if (access (_path.c_str(), R_OK) != 0) {
/* file does not exist or we cannot read it */
if (must_exist) {
error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
goto out;
}
if (errno != ENOENT) {
error << string_compose(_("Filesource: cannot check for existing file (%1): %2"), _path, strerror (errno)) << endmsg;
goto out;
}
/* a new file */
isnew = true;
ret = true;
} else {
/* already exists */
ret = true;
}
}
out:
return ret;
}
void
AudioFileSource::set_search_path (string p)
{
search_path = p;
}
void
AudioFileSource::set_header_position_offset (jack_nframes_t offset, bool negative)
{
time_t tnow;
time (&tnow);
header_position_offset = offset;
header_position_negative = negative;
HeaderPositionOffsetChanged (localtime (&tnow), tnow); /* EMIT SIGNAL */
}
void
AudioFileSource::set_timeline_position (jack_nframes_t pos)
{
timeline_position = pos;
}
void
AudioFileSource::handle_header_position_change (struct tm* now, time_t tnow)
{
/* don't do this if the file has never had its header flushed to disk yet */
if (writable() && _timestamp) {
set_header_timeline_position ();
flush_header ();
}
}
void
AudioFileSource::set_allow_remove_if_empty (bool yn)
{
if (writable()) {
allow_remove_if_empty = yn;
}
}
int
AudioFileSource::set_name (string newname, bool destructive)
{
Glib::Mutex::Lock lm (_lock);
string oldpath = _path;
string newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive);
if (newpath.empty()) {
error << string_compose (_("programming error: %1"), "cannot generate a changed audio path") << endmsg;
return -1;
}
if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
error << string_compose (_("cannot rename audio file for %1 to %2"), _name, newpath) << endmsg;
return -1;
}
_name = Glib::path_get_basename (newpath);
_path = newpath;
return rename_peakfile (peak_path (_path));
}
bool
AudioFileSource::is_empty (string path)
{
/* XXX fix me */
return false;
}

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);

897
libs/ardour/audiosource.cc Normal file
View file

@ -0,0 +1,897 @@
/*
Copyright (C) 2000 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: source.cc 404 2006-03-17 17:39:21Z pauld $
*/
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <float.h>
#include <cerrno>
#include <ctime>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <pbd/xml++.h>
#include <pbd/pthread_utils.h>
#include <ardour/audiosource.h>
#include "i18n.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
sigc::signal<void,AudioSource *> AudioSource::AudioSourceCreated;
pthread_t AudioSource::peak_thread;
bool AudioSource::have_peak_thread = false;
vector<AudioSource*> AudioSource::pending_peak_sources;
Glib::Mutex* AudioSource::pending_peak_sources_lock = 0;
int AudioSource::peak_request_pipe[2];
bool AudioSource::_build_missing_peakfiles = false;
bool AudioSource::_build_peakfiles = false;
AudioSource::AudioSource (string name)
: Source (name)
{
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;
}
_peaks_built = false;
next_peak_clear_should_notify = true;
_read_data_count = 0;
_write_data_count = 0;
}
AudioSource::AudioSource (const XMLNode& node)
: Source (node)
{
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;
}
_peaks_built = false;
next_peak_clear_should_notify = true;
_read_data_count = 0;
_write_data_count = 0;
if (set_state (node)) {
throw failed_constructor();
}
}
AudioSource::~AudioSource ()
{
}
XMLNode&
AudioSource::get_state ()
{
XMLNode& node (Source::get_state());
if (_captured_for.length()) {
node.add_property ("captured-for", _captured_for);
}
return node;
}
int
AudioSource::set_state (const XMLNode& node)
{
const XMLProperty* prop;
Source::set_state (node);
if ((prop = node.property ("captured-for")) != 0) {
_captured_for = prop->value();
}
return 0;
}
/***********************************************************************
PEAK FILE STUFF
***********************************************************************/
void*
AudioSource::peak_thread_work (void* arg)
{
PBD::ThreadCreated (pthread_self(), X_("Peak"));
struct pollfd pfd[1];
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;
}
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()) {
AudioSource* 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
AudioSource::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 << _("AudioSource: could not create peak thread") << endmsg;
return -1;
}
have_peak_thread = true;
return 0;
}
void
AudioSource::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
AudioSource::queue_for_peaks (AudioSource& 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 AudioSource::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
AudioSource::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
AudioSource::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
AudioSource::initialize_peakfile (bool newfile, string audio_path)
{
struct stat statbuf;
peakpath = peak_path (audio_path);
/* Nasty band-aid for older sessions that were created before we
used libsndfile for all audio files.
*/
if (!newfile && access (peakpath.c_str(), R_OK) != 0) {
string str = old_peak_path (audio_path);
if (access (str.c_str(), R_OK) == 0) {
peakpath = str;
}
}
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(_("AudioSource: 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;
}
jack_nframes_t
AudioSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
{
Glib::Mutex::Lock lm (_lock);
return read_unlocked (dst, start, cnt, workbuf);
}
jack_nframes_t
AudioSource::write (Sample *dst, jack_nframes_t cnt, char * workbuf)
{
Glib::Mutex::Lock lm (_lock);
return write_unlocked (dst, cnt, workbuf);
}
int
AudioSource::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(_("AudioSource: 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 << "AudioSource["
<< _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(_("AudioSource: 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 << "AudioSource["
<< _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(_("AudioSource[%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
AudioSource::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
AudioSource::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(_("AudioSource: 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
AudioSource::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
AudioSource::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;
}
}
jack_nframes_t
AudioSource::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(_("AudioSource: 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;
}
void
AudioSource::update_length (jack_nframes_t pos, jack_nframes_t cnt)
{
if (pos + cnt > _length) {
_length = pos+cnt;
}
}

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,90 +255,94 @@ 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;
jack_nframes_t old_file_pos;
if (!writable()) {
return 0;
}
if (_capture_start && _capture_end) {
_capture_start = false;
_capture_end = false;
if (_capture_start && _capture_end) {
_capture_start = false;
_capture_end = false;
/* move to the correct location place */
file_pos = capture_start_frame;
/* move to the correct location place */
file_pos = capture_start_frame;
// split cnt in half
jack_nframes_t subcnt = cnt / 2;
jack_nframes_t ofilepos = file_pos;
// split cnt in half
jack_nframes_t subcnt = cnt / 2;
jack_nframes_t ofilepos = file_pos;
// fade in
if (crossfade (data, subcnt, 1, workbuf) != subcnt) {
return 0;
}
file_pos += subcnt;
Sample * tmpdata = data + subcnt;
// fade out
subcnt = cnt - subcnt;
if (crossfade (tmpdata, subcnt, 0, workbuf) != subcnt) {
return 0;
}
file_pos = ofilepos; // adjusted below
// fade in
if (crossfade (data, subcnt, 1, workbuf) != subcnt) {
return 0;
}
else if (_capture_start) {
_capture_start = false;
_capture_end = false;
/* move to the correct location place */
file_pos = capture_start_frame;
file_pos += subcnt;
Sample * tmpdata = data + subcnt;
if (crossfade (data, cnt, 1, workbuf) != cnt) {
return 0;
}
// fade out
subcnt = cnt - subcnt;
if (crossfade (tmpdata, subcnt, 0, workbuf) != subcnt) {
return 0;
}
} else if (_capture_end) {
_capture_start = false;
_capture_end = false;
file_pos = ofilepos; // adjusted below
}
else if (_capture_start) {
if (crossfade (data, cnt, 0, workbuf) != cnt) {
return 0;
}
_capture_start = false;
_capture_end = false;
/* move to the correct location place */
file_pos = capture_start_frame;
if (crossfade (data, cnt, 1, workbuf) != cnt) {
return 0;
}
} else if (_capture_end) {
_capture_start = false;
_capture_end = false;
if (crossfade (data, cnt, 0, workbuf) != cnt) {
return 0;
}
} else {
if (write_float (data, file_pos, cnt) != cnt) {
return 0;
}
}
old_file_pos = file_pos;
if (file_pos + cnt > _length) {
_length = file_pos + cnt;
}
file_pos += cnt;
if (_build_peakfiles) {
PeakBuildRecord *pbr = 0;
if (pending_peak_builds.size()) {
pbr = pending_peak_builds.back();
}
if (pbr && pbr->frame + pbr->cnt == old_file_pos) {
/* the last PBR extended to the start of the current write,
so just extend it again.
*/
pbr->cnt += cnt;
} else {
if (file_write(data, file_pos, cnt, workbuf) != (ssize_t) cnt) {
return 0;
}
pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt));
}
old_file_pos = file_pos;
if (file_pos + cnt > _length) {
_length = file_pos + cnt;
}
file_pos += cnt;
if (_build_peakfiles) {
PeakBuildRecord *pbr = 0;
if (pending_peak_builds.size()) {
pbr = pending_peak_builds.back();
}
if (pbr && pbr->frame + pbr->cnt == old_file_pos) {
/* 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 (old_file_pos, cnt));
}
_peaks_built = false;
}
_peaks_built = false;
}
if (_build_peakfiles) {
@ -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

@ -1,246 +0,0 @@
/*
Copyright (C) 2006 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/stat.h>
#include <unistd.h>
#include <sys/time.h>
#include <sndfile.h>
#include <pbd/mountpoint.h>
#include <ardour/externalsource.h>
#include <ardour/sndfilesource.h>
#include <ardour/sndfile_helpers.h>
// if these headers come before sigc++ is included
// the parser throws ObjC++ errors. (nil is a keyword)
#ifdef HAVE_COREAUDIO
#include <ardour/coreaudio_source.h>
#include <AudioToolbox/ExtendedAudioFile.h>
#include <AudioToolbox/AudioFormat.h>
#endif // HAVE_COREAUDIO
#include "i18n.h"
using namespace ARDOUR;
string ExternalSource::peak_dir = "";
ExternalSource::ExternalSource (const XMLNode& node)
: Source (node)
{
}
ExternalSource::ExternalSource (const string& idstr, bool build_peak)
: Source(build_peak)
{
}
ExternalSource::~ExternalSource ()
{
}
jack_nframes_t
ExternalSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
{
return read (dst, start, cnt, workbuf);
}
string
ExternalSource::peak_path (string audio_path)
{
/* XXX hardly bombproof! fix me */
struct stat stat_file;
struct stat stat_mount;
string mp = mountpoint (audio_path);
stat (audio_path.c_str(), &stat_file);
stat (mp.c_str(), &stat_mount);
char buf[32];
#ifdef __APPLE__
snprintf (buf, sizeof (buf), "%u-%u-%d.peak", stat_mount.st_ino, stat_file.st_ino, channel);
#else
snprintf (buf, sizeof (buf), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, channel);
#endif
string res = peak_dir;
res += buf;
return res;
}
#ifdef HAVE_COREAUDIO
ExternalSource*
ExternalSource::create (const XMLNode& node)
{
ExternalSource* es = 0;
try {
es = new CoreAudioSource (node);
}
catch (failed_constructor& err) {
es = new SndFileSource (node);
}
es = new SndFileSource (node);
return es;
}
#else
ExternalSource*
ExternalSource::create (const XMLNode& node)
{
return new SndFileSource (node);
}
#endif // HAVE_COREAUDIO
#ifdef HAVE_COREAUDIO
ExternalSource*
ExternalSource::create (const string& idstr, bool build_peak)
{
ExternalSource* es = 0;
try {
es = new CoreAudioSource (idstr, build_peak);
}
catch (failed_constructor& err) {
es = new SndFileSource (idstr, build_peak);
}
return es;
}
#else
ExternalSource*
ExternalSource::create (const string& idstr, bool build_peak)
{
return new SndFileSource (idstr, build_peak);
}
#endif // HAVE_COREAUDIO
#ifdef HAVE_COREAUDIO
std::string
CFStringRefToStdString(CFStringRef stringRef)
{
CFIndex size =
CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef) ,
kCFStringEncodingASCII);
char *buf = new char[size];
std::string result;
if(CFStringGetCString(stringRef, buf, size, kCFStringEncodingASCII)) {
result = buf;
}
delete [] buf;
return result;
}
#endif // HAVE_COREAUDIO
bool
ExternalSource::get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg)
{
#ifdef HAVE_COREAUDIO
OSStatus err = noErr;
FSRef ref;
ExtAudioFileRef af = 0;
size_t size;
CFStringRef name;
err = FSPathMakeRef ((UInt8*)path.c_str(), &ref, 0);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
err = ExtAudioFileOpen(&ref, &af);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
AudioStreamBasicDescription absd;
memset(&absd, 0, sizeof(absd));
size = sizeof(AudioStreamBasicDescription);
err = ExtAudioFileGetProperty(af,
kExtAudioFileProperty_FileDataFormat, &size, &absd);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
_info.samplerate = absd.mSampleRate;
_info.channels = absd.mChannelsPerFrame;
size = sizeof(_info.length);
err = ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &size, &_info.length);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
size = sizeof(CFStringRef);
err = AudioFormatGetProperty(
kAudioFormatProperty_FormatName, sizeof(absd), &absd, &size, &name);
if (err != noErr) {
ExtAudioFileDispose (af);
goto libsndfile;
}
_info.format_name = CFStringRefToStdString(name);
ExtAudioFileDispose (af);
return true;
libsndfile:
#endif // HAVE_COREAUDIO
SNDFILE *sf;
SF_INFO sf_info;
sf_info.format = 0; // libsndfile says to clear this before sf_open().
if ((sf = sf_open ((char*) path.c_str(), SFM_READ, &sf_info)) == 0) {
char errbuf[256];
error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1);
return false;
}
sf_close (sf);
_info.samplerate = sf_info.samplerate;
_info.channels = sf_info.channels;
_info.length = sf_info.frames;
_info.format_name = string_compose("Format: %1, %2",
sndfile_major_format(sf_info.format),
sndfile_minor_format(sf_info.format));
return true;
}

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)
@ -456,10 +456,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;
@ -470,10 +470,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;
@ -882,7 +882,7 @@ Session::playlist_length_changed (Playlist* pl)
}
void
Session::diskstream_playlist_changed (DiskStream* dstream)
Session::diskstream_playlist_changed (AudioDiskstream* dstream)
{
Playlist *playlist;
@ -962,7 +962,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);
@ -980,7 +980,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);
@ -988,7 +988,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());
@ -1069,7 +1069,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;
@ -1257,7 +1257,7 @@ Session::enable_record ()
if (g_atomic_int_get (&_record_status) != Recording) {
g_atomic_int_set (&_record_status, Recording);
_last_record_location = _transport_frame;
//send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe);
deliver_mmc(MIDI::MachineControl::cmdRecordStrobe, _last_record_location);
if (Config->get_use_hardware_monitoring() && auto_input) {
/* Even though this can be called from RT context we are using
@ -1266,7 +1266,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);
}
@ -1292,7 +1292,11 @@ Session::disable_record (bool rt_context, bool force)
}
}
//send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit);
// FIXME: timestamp correct? [DR]
// FIXME FIXME FIXME: rt_context? this must be called in the process thread.
// does this /need/ to be sent in all cases?
if (rt_context)
deliver_mmc (MIDI::MachineControl::cmdRecordExit, _transport_frame);
if (Config->get_use_hardware_monitoring() && auto_input) {
/* Even though this can be called from RT context we are using
@ -1301,7 +1305,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);
}
@ -1328,7 +1332,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);
@ -1353,8 +1357,7 @@ Session::maybe_enable_record ()
enable_record ();
}
} else {
// FIXME
//send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordPause);
deliver_mmc (MIDI::MachineControl::cmdRecordPause, _transport_frame);
RecordStateChanged (); /* EMIT SIGNAL */
}
@ -1434,6 +1437,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 */
@ -1495,7 +1501,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);
}
@ -1902,14 +1908,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
@ -1929,7 +1935,7 @@ Session::add_diskstream (DiskStream* dstream)
set_dirty();
save_state (_current_snapshot_name);
DiskStreamAdded (dstream); /* EMIT SIGNAL */
AudioDiskstreamAdded (dstream); /* EMIT SIGNAL */
}
void
@ -1963,19 +1969,25 @@ Session::remove_route (Route& route)
update_route_solo_state ();
}
{
Glib::RWLock::WriterLock lm (diskstream_lock);
AudioTrack* at;
AudioDiskstream* ds = 0;
AudioTrack* at;
if ((at = dynamic_cast<AudioTrack*>(&route)) != 0) {
ds = &at->disk_stream();
}
if ((at = dynamic_cast<AudioTrack*>(&route)) != 0) {
diskstreams.remove (&at->disk_stream());
at->disk_stream().unref ();
if (ds) {
{
Glib::RWLock::WriterLock lm (diskstream_lock);
audio_diskstreams.remove (ds);
}
find_current_end ();
ds->unref ();
}
find_current_end ();
update_latency_compensation (false, false);
set_dirty();
@ -2257,7 +2269,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;
@ -2267,12 +2279,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;
}
@ -2281,12 +2293,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;
}
@ -2585,7 +2597,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;
}
}
@ -2609,7 +2624,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()) {
@ -2632,15 +2647,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));
@ -2652,13 +2667,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);
}
}
@ -2677,15 +2692,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;
}
return source;
if (source) {
return source;
}
/* XXX search MIDI or other searches here */
return 0;
}
string
@ -2892,17 +2913,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());
}
}
@ -3084,7 +3111,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());
@ -3142,12 +3169,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++;
}
@ -3156,10 +3183,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)();
}
@ -3186,7 +3213,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 ();
}
}
@ -3469,7 +3496,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);
}
}
@ -3489,7 +3516,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);
}
@ -3564,12 +3591,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;
@ -3614,7 +3641,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) {
@ -3653,9 +3684,13 @@ 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) {
goto out;
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;
}
}
}
@ -3673,14 +3708,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;
@ -3688,8 +3729,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"
@ -393,11 +393,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

@ -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/slave.h>
#include <ardour/cycles.h>
#include <ardour/smpte.h>
@ -1016,10 +1016,15 @@ Session::send_mmc_in_another_thread (MIDI::MachineControl::Command cmd, jack_nfr
poke_midi_thread ();
}
*/
/** Send an MMC command at the given absolute timestamp (@a where).
*
* This must be called in the process thread, and @a where must fall within
* this process cycle or horrible things will happen.
*/
void
Session::deliver_mmc (MIDI::MachineControl::Command cmd, jack_nframes_t where)
{
#if 0
using namespace MIDI;
int nbytes = 4;
SMPTE::Time smpte;
@ -1030,7 +1035,7 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, jack_nframes_t where)
mmc_buffer[nbytes++] = cmd;
// cerr << "delivering MMC, cmd = " << hex << (int) cmd << dec << endl;
cerr << "delivering MMC, cmd = " << hex << (int) cmd << dec << endl;
switch (cmd) {
case MachineControl::cmdLocate:
@ -1050,6 +1055,7 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, jack_nframes_t where)
case MachineControl::cmdPlay:
/* always convert Play into Deferred Play */
/* Why? [DR] */
mmc_buffer[4] = MachineControl::cmdDeferredPlay;
break;
@ -1073,14 +1079,13 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, jack_nframes_t where)
mmc_buffer[nbytes++] = 0xf7; // terminate SysEx/MMC message
Glib::Mutex::Lock lm (midi_lock);
//Glib::Mutex::Lock lm (midi_lock);
if (_mmc_port->write (mmc_buffer, nbytes) != nbytes) {
// FIXME: timestamp correct? [DR]
if (_mmc_port->write (mmc_buffer, nbytes, where - _transport_frame) != nbytes) {
error << string_compose(_("MMC: cannot send command %1%2%3"), &hex, cmd, &dec) << endmsg;
}
}
#endif
cout << "MMC support broken." << endl;
}
bool

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>
@ -74,7 +74,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 ();
}
}
@ -146,12 +146,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 ();
}
@ -185,12 +185,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 ();
}
@ -209,7 +209,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;
@ -579,7 +579,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;
@ -587,7 +587,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,23 +1881,12 @@ 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;
return 0;
}
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;
@ -3016,17 +3019,14 @@ Session::cleanup_sources (Session::cleanup_report& rep)
find_all_sources_across_snapshots (all_sources, true);
/* add our current source list
/* 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"
@ -95,6 +96,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 */
}
@ -103,6 +107,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 */
}
@ -326,7 +333,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,13 +152,16 @@ 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");
r = new AudioRegion (sources, 0, sources.front()->length(), region_name,
0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile));
0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile));
out:

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()));
@ -494,7 +494,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);
}
@ -502,7 +502,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);
}
@ -532,7 +532,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);
}
@ -653,7 +653,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);
@ -668,7 +668,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);
@ -714,7 +714,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);
@ -740,7 +740,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);
@ -791,7 +791,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);
}
@ -881,7 +881,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);
}
@ -1016,7 +1016,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;
@ -1048,7 +1048,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);
@ -1244,7 +1244,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)) {
sf_close (sf);
sf = 0;
throw failed_constructor ();
}
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;
}
}
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,49 +282,73 @@ 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 (sf_seek (sf, (off_t) start, SEEK_SET) < 0) {
char errbuf[256];
sf_error_str (0, errbuf, sizeof (errbuf) - 1);
error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), errbuf) << endmsg;
return 0;
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 (_info.channels == 1) {
jack_nframes_t ret = sf_read_float (sf, dst, cnt);
_read_data_count = cnt * sizeof(float);
return ret;
if (file_cnt) {
if (sf_seek (sf, (off_t) start, SEEK_SET) < 0) {
char errbuf[256];
sf_error_str (0, errbuf, sizeof (errbuf) - 1);
error << string_compose(_("SndFileSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), errbuf) << endmsg;
return 0;
}
if (_info.channels == 1) {
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;
}
tmpbufsize = real_cnt;
tmpbuf = new float[tmpbufsize];
if (interleave_buf) {
delete [] interleave_buf;
}
interleave_bufsize = real_cnt;
interleave_buf = new float[interleave_bufsize];
}
nread = sf_read_float (sf, tmpbuf, real_cnt);
ptr = tmpbuf + channel;
nread /= _info.channels;
nread = sf_read_float (sf, interleave_buf, real_cnt);
ptr = interleave_buf + channel;
nread /= _info.channels;
/* stride through the interleaved data */
/* stride through the interleaved data */
for (int32_t n = 0; n < nread; ++n) {
dst[n] = *ptr;
ptr += _info.channels;
}
for (int32_t n = 0; n < nread; ++n) {
dst[n] = *ptr;
ptr += _info.channels;
}
_read_data_count = cnt * sizeof(float);
@ -166,3 +356,163 @@ SndFileSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char
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;
}

14
libs/libsndfile/AUTHORS Normal file
View file

@ -0,0 +1,14 @@
The main author of libsndfile is Erik de Castro Lopo <erikd@mega-nerd.com>.
The code in the src/GSM610 directory was written by Jutta Degener
<jutta@cs.tu-berlin.de> and Carsten Bormann <cabo@cs.tu-berlin.de>.
They should not be contacted in relation to libsndfile or the GSM 6.10 code
that is part of libsndfile. Their original code can be found at:
http://kbs.cs.tu-berlin.de/~jutta/toast.html
Code in the src/G72x directory was released by Sun Microsystems, Inc. to the
public domain. Minor modifications were required to integrate these files
into libsndfile. The changes are listed in src/G72x/ChangeLog.

6107
libs/libsndfile/ChangeLog Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
#!/bin/sh
# Copyright (C) 2006 Erik de Castro Lopo <erikd@mega-nerd.com>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the author nor the names of any contributors may be used
# to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -e
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
echo "Usage : Mingw-make-dist.sh <source tarball>."
exit 1
fi
TARGZ=$1
if [ ! -f $TARGZ ]; then
echo "Can't find source tarball."
fi
TARGZ=$1
if [ ! -f $TARGZ.asc ]; then
echo "Can't find source tarball signature."
fi
UNAME=`uname -s`
if [ x$UNAME != "xMINGW32_NT-5.1" ]; then
echo "Not able to build Win32 binaries on this platform."
fi
echo "Building MinGW binary/source zip file."
VERSION=`pwd | sed -e "s#.*/##" | sed -e s/libsndfile-//`
BUILD=`echo $VERSION | sed -e "s/\./_/g"`
INSTALL="libsndfile-$BUILD"
ZIPNAME="$INSTALL.zip"
if [ -z "$BUILD" ]; then
echo "Bad BUILD variable : '$BUILD'"
exit 1
fi
if [ ! -d $INSTALL/ ]; then
mkdir $INSTALL
fi
if [ ! -f config.status ]; then
./configure --prefix=`pwd`/$INSTALL/
else
teststr=`grep "with options" config.status | grep -- --prefix=`
if [ -z "$teststr" ]; then
# --disable-static doesn't work.
./configure --prefix=`pwd`/$INSTALL/
fi
fi
if [ ! -f src/.libs/libsndfile-1.dll ]; then
make all check
fi
if [ ! -f $INSTALL/bin/libsndfile-1.dll ]; then
make install
rm -f $INSTALL/bin/sndfile-regtest.exe
strip $INSTALL/bin/*.*
mv $INSTALL/bin/*.* $INSTALL/include/*.* $INSTALL/
rmdir $INSTALL/bin
rm -rf $INSTALL/lib
rmdir $INSTALL/include
cp src/libsndfile.def $INSTALL/
cp Win32/README-precompiled-dll.txt $INSTALL/
fi
if [ ! -f $INSTALL/libsndfile-$VERSION.tar.gz ]; then
cp $TARGZ $INSTALL/
if [ -f $TARGZ.asc ]; then
cp $TARGZ.asc $INSTALL/
fi
fi
if [ ! -f $ZIPNAME ]; then
zip -r $ZIPNAME $INSTALL/
fi
# Do not edit or modify anything in this comment block.
# The following line is a file identity tag for the GNU Arch
# revision control system.
#
# arch-tag: 3f82cd8a-f800-48d7-9646-2cdcf03c81a0

126
libs/libsndfile/NEWS Normal file
View file

@ -0,0 +1,126 @@
Version 1.0.16 (2006-04-30)
* Add support for Broadcast (BEXT) chunks in WAV files.
* Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS.
* Add support for RIFX (big endian WAV variant).
* Fix configure script bugs.
* Fix bug in INST and MARK chunk writing for AIFF files.
Version 1.0.15 (2006-03-16)
* Fix some ia64 issues.
* Fix precompiled DLL.
* Minor bug fixes.
Version 1.0.14 (2006-02-19)
* Really fix MinGW compile problems.
* Minor bug fixes.
Version 1.0.13 (2006-01-21)
* Fix for MinGW compiler problems.
* Allow readin/write of instrument chunks from WAV and AIFF files.
* Compile problem fix for Solaris compiler.
* Minor cleanups and bug fixes.
Version 1.0.12 (2005-09-30)
* Add support for FLAC and Apple's Core Audio Format (CAF).
* Add virtual I/O interface (still needs docs).
* Cygwin and other Win32 fixes.
* Minor bug fixes and cleanups.
Version 1.0.11 (2004-11-15)
* Add support for SD2 files.
* Add read support for loop info in WAV and AIFF files.
* Add more tests.
* Improve type safety.
* Minor optimisations and bug fixes.
Version 1.0.10 (2004-06-15)
* Fix AIFF read/write mode bugs.
* Add support for compiling Win32 DLLS using MinGW.
* Fix problems resulting in failed compiles with gcc-2.95.
* Improve test suite.
* Minor bug fixes.
Version 1.0.9 (2004-03-30)
* Add handling of AVR (Audio Visual Research) files.
* Improve handling of WAVEFORMATEXTENSIBLE WAV files.
* Fix for using pipes on Win32.
Version 1.0.8 (2004-03-14)
* Correct peak chunk handing for files with > 16 tracks.
* Fix for WAV files with huge number of CUE chunks.
Version 1.0.7 (2004-02-25)
* Fix clip mode detection on ia64, MIPS and other CPUs.
* Fix two MacOSX build problems.
Version 1.0.6 (2004-02-08)
* Added support for native Win32 file access API (Ross Bencina).
* New mode to add clippling then a converting from float/double to integer
would otherwise wrap around.
* Fixed a bug in reading/writing files > 2Gig on Linux, Solaris and others.
* Many minor bug fixes.
* Other random fixes for Win32.
Version 1.0.5 (2003-05-03)
* Added support for HTK files.
* Added new function sf_open_fd() to allow for secure opening of temporary
files as well as reading/writing sound files embedded within larger
container files.
* Added string support for AIFF files.
* Minor bug fixes and code cleanups.
Version 1.0.4 (2003-02-02)
* Added suport of PVF and XI files.
* Added functionality for setting and retreiving strings from sound files.
* Minor code cleanups and bug fixes.
Version 1.0.3 (2002-12-09)
* Minor bug fixes.
Version 1.0.2 (2002-11-24)
* Added support for VOX ADPCM.
* Improved error reporting.
* Added version scripting on Linux and Solaris.
* Minor bug fixes.
Version 1.0.1 (2002-09-14)
* Added MAT and MAT5 file formats.
* Minor bug fixes.
Version 1.0.0 (2002-08-16)
* Final release for 1.0.0.
Version 1.0.0rc6 (2002-08-14)
* Release candidate 6 for the 1.0.0 series.
* MacOS9 fixes.
Version 1.0.0rc5 (2002-08-10)
* Release candidate 5 for the 1.0.0 series.
* Changed the definition of sf_count_t which was causing problems when
libsndfile was compiled with other libraries (ie WxWindows).
* Minor bug fixes.
* Documentation cleanup.
Version 1.0.0rc4 (2002-08-03)
* Release candidate 4 for the 1.0.0 series.
* Minor bug fixes.
* Fix broken Win32 "make check".
Version 1.0.0rc3 (2002-08-02)
* Release candidate 3 for the 1.0.0 series.
* Fix bug where libsndfile was reading beyond the end of the data chunk.
* Added on-the-fly header updates on write.
* Fix a couple of documentation issues.
Version 1.0.0rc2 (2002-06-24)
* Release candidate 2 for the 1.0.0 series.
* Fix compile problem for Win32.
Version 1.0.0rc1 (2002-06-24)
* Release candidate 1 for the 1.0.0 series.
Version 0.0.28 (2002-04-27)
* Last offical release of 0.0.X series of the library.
Version 0.0.8 (1999-02-16)
* First offical release.

71
libs/libsndfile/README Normal file
View file

@ -0,0 +1,71 @@
This is libsndfile, 1.0.16
libsndfile is a library of C routines for reading and writing
files containing sampled audio data.
The src/ directory contains the source code for library itself.
The doc/ directory contains the libsndfile documentation.
The examples/ directory contains examples of how to write code using
libsndfile. 'wav32_aiff24' converts a WAV file containing 32 bit floating
point data into a 24 bit PCM AIFF file. 'sndfile2oct' dumps the audio
data of a file in a human readable format. 'sfconvert' is the beginnings
of a audio file format conversion utility. 'make_sine' generates a WAV
file containing one cycle of a sine wave with 4096 sample points in
32 bit floating point format. 'sfinfo' opens a sound file and prints
out information about that file.
The tests/ directory contains programs which link against libsndfile
and test its functionality.
The Win32/ directory contains files and documentation to allow libsndfile
to compile under Win32 with the Microsoft Visual C++ compiler.
The src/GSM610 directory contains code written by Jutta Degener and Carsten
Bormann. Their original code can be found at :
http://kbs.cs.tu-berlin.de/~jutta/toast.html
The src/G72x directory contains code written and released by Sun Microsystems
under a suitably free license.
Win32
-----
There are detailed instructions for building libsndfile on Win32 in the file
doc/win32.html
MacOSX
------
Building on MacOSX should be the same as building it on any other Unix.
OTHER PLATFORMS
---------------
To compile libsndfile on platforms which have a Bourne Shell compatible
shell, an ANSI C compiler and a make utility should require no more that
the following three commands :
./configure
make
make install
For platforms without the required shell, it is usually sufficient to
create an approriate config.h file in the src/ directory with correct
values for the following #defines (this would work for AmigaOS) :
#define HAVE_ENDIAN_H 0
#define GUESS_BIG_ENDIAN 1
#define GUESS_LITTLE_ENDIAN 0
#define FORCE_BROKEN_FLOAT 0
CONTACTS
--------
libsndfile was written by Erik de Castro Lopo (erikd AT mega-nerd DOT com).
The libsndfile home page is at :
http://www.mega-nerd.com/libsndfile/

Some files were not shown because too many files have changed in this diff Show more