mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
Merged with trunk revision 600
git-svn-id: svn://localhost/ardour2/branches/midi@601 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
a8f44b1556
commit
b5db1f624d
205 changed files with 70728 additions and 2113 deletions
|
|
@ -1,3 +1,3 @@
|
|||
Last merged with trunk revision:
|
||||
|
||||
579
|
||||
600
|
||||
|
|
|
|||
26
SConstruct
26
SConstruct
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ gtkardour.Merge ([
|
|||
libraries['libgnomecanvasmm'],
|
||||
libraries['sysmidi'],
|
||||
libraries['sndfile'],
|
||||
libraries['flac'],
|
||||
libraries['lrdf'],
|
||||
libraries['glibmm2'],
|
||||
libraries['pangomm'],
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -207,6 +207,8 @@
|
|||
<menu action='AudioFileFormatHeader'>
|
||||
<menuitem action='FileHeaderFormatBWF'/>
|
||||
<menuitem action='FileHeaderFormatWAVE'/>
|
||||
<menuitem action='FileHeaderFormatWAVE64'/>
|
||||
<menuitem action='FileHeaderFormatCAF'/>
|
||||
</menu>
|
||||
</menu>
|
||||
<menu action='Autoconnect'>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace ALSA {
|
|||
|
||||
namespace ARDOUR {
|
||||
class Session;
|
||||
class DiskStream;
|
||||
class AudioDiskstream;
|
||||
class RouteGroup;
|
||||
class Redirect;
|
||||
class Insert;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include <ardour/location.h>
|
||||
#include <ardour/diskstream.h>
|
||||
#include <ardour/audio_diskstream.h>
|
||||
|
||||
#include "editor.h"
|
||||
#include "editing.h"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
|
||||
#include <ardour/diskstream.h>
|
||||
#include <ardour/audio_diskstream.h>
|
||||
#include <ardour/audioplaylist.h>
|
||||
|
||||
#include "editor.h"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -458,7 +458,6 @@ main (int argc, char *argv[])
|
|||
ui = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
delete engine;
|
||||
ARDOUR::cleanup ();
|
||||
shutdown (0);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace ARDOUR {
|
|||
class Route;
|
||||
class RouteGroup;
|
||||
class Session;
|
||||
class DiskStream;
|
||||
class AudioDiskstream;
|
||||
class AudioEngine;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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':
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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']:
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
157
libs/ardour/ardour/audiofilesource.h
Normal file
157
libs/ardour/ardour/audiofilesource.h
Normal 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__ */
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
166
libs/ardour/ardour/audiosource.h
Normal file
166
libs/ardour/ardour/audiosource.h
Normal 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__ */
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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*>(®ion->source (n));
|
||||
(*chan).write_source = dynamic_cast<AudioFileSource*>(®ion->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);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
661
libs/ardour/audiofilesource.cc
Normal file
661
libs/ardour/audiofilesource.cc
Normal 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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
897
libs/ardour/audiosource.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
14
libs/libsndfile/AUTHORS
Normal 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
6107
libs/libsndfile/ChangeLog
Normal file
File diff suppressed because it is too large
Load diff
113
libs/libsndfile/Mingw-make-dist.sh
Executable file
113
libs/libsndfile/Mingw-make-dist.sh
Executable 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
126
libs/libsndfile/NEWS
Normal 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
71
libs/libsndfile/README
Normal 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
Loading…
Add table
Add a link
Reference in a new issue