From 55a85aa2a906d56818a35172594762a637d85f6d Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 13 Nov 2006 17:56:43 +0000 Subject: display timecode from BWF etc in SF browser; accels for windows now work (misspelling in ardour.bindings); use hide icon in automation tracks git-svn-id: svn://localhost/ardour2/trunk@1125 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/actions.cc | 3 ++ gtk2_ardour/ardour.bindings | 8 +-- gtk2_ardour/automation_time_axis.cc | 2 +- gtk2_ardour/sfdb_ui.cc | 11 ++-- gtk2_ardour/sfdb_ui.h | 1 + libs/ardour/ardour/audiofilesource.h | 5 +- libs/ardour/ardour/coreaudiosource.h | 2 + libs/ardour/ardour/destructive_filesource.h | 2 +- libs/ardour/ardour/sndfilesource.h | 6 ++- libs/ardour/audiofilesource.cc | 77 +++----------------------- libs/ardour/coreaudiosource.cc | 50 +++++++++++++++++ libs/ardour/sndfilesource.cc | 83 +++++++++++++++++++++-------- libs/pbd/convert.cc | 37 ++++++++++--- libs/pbd/pbd/convert.h | 3 +- 14 files changed, 179 insertions(+), 111 deletions(-) diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc index 885a23ffc7..88d0187592 100644 --- a/gtk2_ardour/actions.cc +++ b/gtk2_ardour/actions.cc @@ -89,6 +89,7 @@ RefPtr ActionManager::register_action (RefPtr group, const char * name, const char * label, slot sl, guint key, Gdk::ModifierType mods) { RefPtr act = register_action (group, name, label, sl); + cerr << "Reset A accel for " << name << endl; AccelMap::add_entry (act->get_accel_path(), key, mods); return act; @@ -121,6 +122,7 @@ RefPtr ActionManager::register_radio_action (RefPtr group, RadioAction::Group& rgroup, const char * name, const char * label, slot sl, guint key, Gdk::ModifierType mods) { RefPtr act = register_radio_action (group, rgroup, name, label, sl); + cerr << "Reset B accel for " << name << endl; AccelMap::add_entry (act->get_accel_path(), key, mods); return act; @@ -141,6 +143,7 @@ RefPtr ActionManager::register_toggle_action (RefPtr group, const char * name, const char * label, slot sl, guint key, Gdk::ModifierType mods) { RefPtr act = register_toggle_action (group,name, label, sl); + cerr << "Reset C accel for " << name << endl; AccelMap::add_entry (act->get_accel_path(), key, mods); return act; diff --git a/gtk2_ardour/ardour.bindings b/gtk2_ardour/ardour.bindings index 244e21436c..5a0eb469b7 100644 --- a/gtk2_ardour/ardour.bindings +++ b/gtk2_ardour/ardour.bindings @@ -37,10 +37,10 @@ (gtk_accel_path "/Common/goto-editor" "e") (gtk_accel_path "/Common/goto-mixer" "m") -(gtk-accel_path "/Common/ToggleSoundFileBrowser" "f") -(gtk-accel_path "/Common/ToggleLocations" "l") -(gtk-accel_path "/Common/ToggleBigClock" "b") -(gtk-accel_path "/Common/ToggleColorManager" "c") +(gtk_accel_path "/Common/ToggleSoundFileBrowser" "f") +(gtk_accel_path "/Common/ToggleLocations" "l") +(gtk_accel_path "/Common/ToggleBigClock" "b") +(gtk_accel_path "/Common/ToggleColorManager" "c") (gtk_accel_path "/Editor/editor-copy" "c") (gtk_accel_path "/Common/Quit" "q") diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 147e6ff0d1..9375a90544 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -67,7 +67,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (Session& s, boost::shared_ptrsignal_event().connect (bind (mem_fun (editor, &PublicEditor::canvas_automation_track_event), base_rect, this)); - hide_button.add (*(manage (new Gtk::Image (get_xpm("small_x.xpm"))))); + hide_button.add (*(manage (new Gtk::Image (::get_icon("hide"))))); height_button.set_name ("TrackSizeButton"); auto_button.set_name ("TrackVisualButton"); diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index ab12356989..150b071661 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -74,6 +74,7 @@ SoundFileBox::SoundFileBox () main_box.pack_start(format, false, false); main_box.pack_start(channels, false, false); main_box.pack_start(samplerate, false, false); + main_box.pack_start(timecode, false, false); main_box.pack_start(field_view, true, true); main_box.pack_start(top_box, false, false); main_box.pack_start(bottom_box, false, false); @@ -129,21 +130,25 @@ SoundFileBox::setup_labels (string filename) path = filename; string error_msg; + if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) { return false; } length.set_alignment (0.0f, 0.0f); - length.set_text (string_compose("Length: %1", PBD::length2string(sf_info.length, sf_info.samplerate))); + length.set_text (string_compose(_("Length: %1"), PBD::length2string(sf_info.length, sf_info.samplerate))); format.set_alignment (0.0f, 0.0f); format.set_text (sf_info.format_name); channels.set_alignment (0.0f, 0.0f); - channels.set_text (string_compose("Channels: %1", sf_info.channels)); + channels.set_text (string_compose(_("Channels: %1"), sf_info.channels)); samplerate.set_alignment (0.0f, 0.0f); - samplerate.set_text (string_compose("Samplerate: %1", sf_info.samplerate)); + samplerate.set_text (string_compose(_("Samplerate: %1"), sf_info.samplerate)); + + timecode.set_alignment (0.0f, 0.0f); + timecode.set_text (string_compose (_("Timecode: %1"), PBD::length2string(sf_info.timecode, sf_info.samplerate))); setup_fields (); diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h index 8ef57d7b9f..d7c2c14014 100644 --- a/gtk2_ardour/sfdb_ui.h +++ b/gtk2_ardour/sfdb_ui.h @@ -77,6 +77,7 @@ class SoundFileBox : public Gtk::VBox Gtk::Label format; Gtk::Label channels; Gtk::Label samplerate; + Gtk::Label timecode; Gtk::TreeView field_view; Glib::RefPtr fields; diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h index 728432db81..66cc240770 100644 --- a/libs/ardour/ardour/audiofilesource.h +++ b/libs/ardour/ardour/audiofilesource.h @@ -31,6 +31,7 @@ struct SoundFileInfo { uint16_t channels; int64_t length; std::string format_name; + int64_t timecode; }; class AudioFileSource : public AudioSource { @@ -126,7 +127,7 @@ class AudioFileSource : public AudioSource { string _path; Flag _flags; string _take_id; - uint64_t timeline_position; + int64_t timeline_position; bool file_is_new; bool _is_embedded; @@ -141,7 +142,7 @@ class AudioFileSource : public AudioSource { static uint64_t header_position_offset; - virtual void set_timeline_position (nframes_t pos); + virtual void set_timeline_position (int64_t pos); virtual void set_header_timeline_position () = 0; bool find (std::string path, bool must_exist, bool& is_new); diff --git a/libs/ardour/ardour/coreaudiosource.h b/libs/ardour/ardour/coreaudiosource.h index 5f54d01f5d..bd69c78e18 100644 --- a/libs/ardour/ardour/coreaudiosource.h +++ b/libs/ardour/ardour/coreaudiosource.h @@ -38,6 +38,8 @@ class CoreAudioSource : public AudioFileSource { int flush_header () {return 0;}; void set_header_timeline_position () {}; + static int get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg); + protected: nframes_t read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const; nframes_t write_unlocked (Sample *dst, nframes_t cnt) { return 0; } diff --git a/libs/ardour/ardour/destructive_filesource.h b/libs/ardour/ardour/destructive_filesource.h index d2cae73ddf..2e6f5d0e57 100644 --- a/libs/ardour/ardour/destructive_filesource.h +++ b/libs/ardour/ardour/destructive_filesource.h @@ -68,7 +68,7 @@ class DestructiveFileSource : public SndFileSource { void init (); nframes_t crossfade (Sample* data, nframes_t cnt, int dir); - void set_timeline_position (nframes_t); + void set_timeline_position (int64_t); }; } diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h index 66d5c1b0d1..1d07f6888d 100644 --- a/libs/ardour/ardour/sndfilesource.h +++ b/libs/ardour/ardour/sndfilesource.h @@ -60,6 +60,8 @@ class SndFileSource : public AudioFileSource { static void setup_standard_crossfades (nframes_t sample_rate); static const AudioFileSource::Flag default_writable_flags; + static int get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg); + protected: void set_header_timeline_position (); @@ -96,10 +98,12 @@ class SndFileSource : public AudioFileSource { Sample* xfade_buf; nframes_t crossfade (Sample* data, nframes_t cnt, int dir); - void set_timeline_position (nframes_t); + void set_timeline_position (int64_t); nframes_t destructive_write_unlocked (Sample *dst, nframes_t cnt); nframes_t nondestructive_write_unlocked (Sample *dst, nframes_t cnt); void handle_header_position_change (); + + static int64_t get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists); }; } // namespace ARDOUR diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc index 1fbde870a0..6999151a1c 100644 --- a/libs/ardour/audiofilesource.cc +++ b/libs/ardour/audiofilesource.cc @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -178,80 +177,16 @@ 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; + if (CoreAudioSource::get_soundfile_info (path, _info, error_msg) == 0) { + return true; } - - 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; + if (SndFileSource::get_soundfile_info (path, _info, error_msg) != 0) { + return true; } - 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; + return false; } XMLNode& @@ -540,7 +475,7 @@ AudioFileSource::set_header_position_offset (nframes_t offset) } void -AudioFileSource::set_timeline_position (nframes_t pos) +AudioFileSource::set_timeline_position (int64_t pos) { timeline_position = pos; } diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc index 83103a6bd4..3c81b18fd4 100644 --- a/libs/ardour/coreaudiosource.cc +++ b/libs/ardour/coreaudiosource.cc @@ -185,3 +185,53 @@ CoreAudioSource::update_header (nframes_t when, struct tm&, time_t) { return 0; } + +int +CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg) +{ + FSRef ref; + ExtAudioFileRef af = 0; + size_t size; + CFStringRef name; + int ret = -1; + + if (FSPathMakeRef ((UInt8*)path.c_str(), &ref, 0) != noErr) { + goto out; + } + + if (ExtAudioFileOpen(&ref, &af) != noErr) { + goto out; + } + + AudioStreamBasicDescription absd; + memset(&absd, 0, sizeof(absd)); + size = sizeof(AudioStreamBasicDescription); + if (ExtAudioFileGetProperty (af, kExtAudioFileProperty_FileDataFormat, &size, &absd) != noErr) { + goto out; + } + + _info.samplerate = absd.mSampleRate; + _info.channels = absd.mChannelsPerFrame; + + size = sizeof(_info.length); + if (ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &size, &_info.length) != noErr) { + goto out; + } + + size = sizeof(CFStringRef); + if (AudioFormatGetProperty(kAudioFormatProperty_FormatName, sizeof(absd), &absd, &size, &name) != noErr) { + goto out; + } + + _info.format_name = CFStringRefToStdString(name); + + // XXX it would be nice to find a way to get this information if it exists + + _info.timecode = 0; + ret = 0; + + out: + ExtAudioFileDispose (af); + return ret; + +} diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 4b9c7ff33b..91605049ca 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -28,7 +28,7 @@ #include #include - +#include #include #include "i18n.h" @@ -243,27 +243,14 @@ SndFileSource::open () _broadcast_info = new SF_BROADCAST_INFO; memset (_broadcast_info, 0, sizeof (*_broadcast_info)); - /* lookup broadcast info */ - - if (sf_command (sf, SFC_GET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) { - - /* if the file has data but no broadcast info, then clearly, there is no broadcast info */ - - if (_length) { - delete _broadcast_info; - _broadcast_info = 0; - _flags = Flag (_flags & ~Broadcast); - } + bool timecode_info_exists; - set_timeline_position (header_position_offset); + set_timeline_position (get_timecode_info (sf, _broadcast_info, timecode_info_exists)); - } else { - - /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits - of the time reference. - */ - - set_timeline_position ( _broadcast_info->time_reference_low ); + if (!timecode_info_exists) { + delete _broadcast_info; + _broadcast_info = 0; + _flags = Flag (_flags & ~Broadcast); } if (writable()) { @@ -893,7 +880,7 @@ SndFileSource::setup_standard_crossfades (nframes_t rate) } void -SndFileSource::set_timeline_position (nframes_t pos) +SndFileSource::set_timeline_position (int64_t pos) { // destructive track timeline postion does not change // except at instantion or when header_position_offset @@ -903,3 +890,57 @@ SndFileSource::set_timeline_position (nframes_t pos) AudioFileSource::set_timeline_position (pos); } } + +int +SndFileSource::get_soundfile_info (string path, SoundFileInfo& info, string& error_msg) +{ + SNDFILE *sf; + SF_INFO sf_info; + SF_BROADCAST_INFO binfo; + bool timecode_exists; + + 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; + } + + 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)); + + memset (&binfo, 0, sizeof (binfo)); + info.timecode = get_timecode_info (sf, &binfo, timecode_exists); + + if (!timecode_exists) { + info.timecode = 0; + } + + sf_close (sf); + + return true; +} + +int64_t +SndFileSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists) +{ + if (sf_command (sf, SFC_GET_BROADCAST_INFO, binfo, sizeof (*binfo)) != SF_TRUE) { + exists = false; + return (header_position_offset); + } + + /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits + of the time reference. + */ + + exists = true; + int64_t ret = (uint32_t) binfo->time_reference_high; + ret <<= 32; + ret |= (uint32_t) binfo->time_reference_low; + return ret; +} diff --git a/libs/pbd/convert.cc b/libs/pbd/convert.cc index 3b709d8e42..832c54acd8 100644 --- a/libs/pbd/convert.cc +++ b/libs/pbd/convert.cc @@ -19,6 +19,10 @@ #include #include +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include #include "pbd/convert.h" @@ -190,23 +194,44 @@ url_decode (string& url) } } +#if 0 string length2string (const int32_t frames, const float sample_rate) { - int secs = (int) (frames / sample_rate); - int hrs = secs / 3600; + int32_t secs = (int32_t) (frames / sample_rate); + int32_t hrs = secs / 3600; secs -= (hrs * 3600); - int mins = secs / 60; + int32_t mins = secs / 60; secs -= (mins * 60); - int total_secs = (hrs * 3600) + (mins * 60) + secs; - int frames_remaining = (int) floor (frames - (total_secs * sample_rate)); + int32_t total_secs = (hrs * 3600) + (mins * 60) + secs; + int32_t frames_remaining = (int) floor (frames - (total_secs * sample_rate)); float fractional_secs = (float) frames_remaining / sample_rate; char duration_str[32]; - sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs); + sprintf (duration_str, "%02" PRIi32 ":%02" PRIi32 ":%05.2f", hrs, mins, (float) secs + fractional_secs); return duration_str; } +#endif + +string +length2string (const int64_t frames, const double sample_rate) +{ + int64_t secs = (int64_t) floor (frames / sample_rate); + int64_t hrs = secs / 3600LL; + secs -= (hrs * 3600LL); + int64_t mins = secs / 60LL; + secs -= (mins * 60LL); + + int64_t total_secs = (hrs * 3600LL) + (mins * 60LL) + secs; + int64_t frames_remaining = (int64_t) floor (frames - (total_secs * sample_rate)); + float fractional_secs = (float) frames_remaining / sample_rate; + + char duration_str[64]; + sprintf (duration_str, "%02" PRIi64 ":%02" PRIi64 ":%05.2f", hrs, mins, (float) secs + fractional_secs); + + return duration_str; +} } // namespace PBD diff --git a/libs/pbd/pbd/convert.h b/libs/pbd/pbd/convert.h index e838b756bc..55006529ae 100644 --- a/libs/pbd/pbd/convert.h +++ b/libs/pbd/pbd/convert.h @@ -31,7 +31,8 @@ int atoi (const std::string&); double atof (const std::string&); void url_decode (std::string&); -std::string length2string (const int32_t frames, const float sample_rate); +// std::string length2string (const int32_t frames, const float sample_rate); +std::string length2string (const int64_t frames, const double sample_rate); std::vector internationalize (const char *, const char **); -- cgit v1.2.3