summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/ardour/lua_api.h29
-rw-r--r--libs/ardour/lua_api.cc122
-rw-r--r--libs/ardour/luabindings.cc21
3 files changed, 171 insertions, 1 deletions
diff --git a/libs/ardour/ardour/lua_api.h b/libs/ardour/ardour/lua_api.h
index 017246cf1d..f56a640ca1 100644
--- a/libs/ardour/ardour/lua_api.h
+++ b/libs/ardour/ardour/lua_api.h
@@ -157,13 +157,40 @@ namespace ARDOUR { namespace LuaAPI {
*/
int hsla_to_rgba (lua_State *lua);
- /* Creates a filename from a series of elements using the correct separator for filenames.
+ /**
+ * Creates a filename from a series of elements using the correct separator for filenames.
*
* No attempt is made to force the resulting filename to be an absolute path.
* If the first element is a relative path, the result will be a relative path.
*/
int build_filename (lua_State *lua);
+ /**
+ * Generic conversion from audio sample count to timecode.
+ * (TimecodeType, sample-rate, sample-pos)
+ */
+ int sample_to_timecode (lua_State *L);
+
+ /**
+ * Generic conversion from timecode to audio sample count.
+ * (TimecodeType, sample-rate, hh, mm, ss, ff)
+ */
+ int timecode_to_sample (lua_State *L);
+
+ /**
+ * Use current session settings to convert
+ * audio-sample count into hh, mm, ss, ff
+ * timecode (this include session pull up/down).
+ */
+ int sample_to_timecode_lua (lua_State *L);
+
+ /**
+ * Use current session settings to convert
+ * timecode (hh, mm, ss, ff) to audio-sample
+ * count (this include session pull up/down).
+ */
+ int timecode_to_sample_lua (lua_State *L);
+
class Vamp {
/** Vamp Plugin Interface
*
diff --git a/libs/ardour/lua_api.cc b/libs/ardour/lua_api.cc
index 6a2dbbe9f6..5af9a6c960 100644
--- a/libs/ardour/lua_api.cc
+++ b/libs/ardour/lua_api.cc
@@ -253,6 +253,128 @@ ARDOUR::LuaAPI::plugin_automation (lua_State *L)
}
int
+ARDOUR::LuaAPI::sample_to_timecode (lua_State *L)
+{
+ int top = lua_gettop (L);
+ if (top < 3) {
+ return luaL_argerror (L, 1, "invalid number of arguments sample_to_timecode (TimecodeFormat, sample_rate, sample)");
+ }
+ typedef Timecode::TimecodeFormat T;
+ T tf = luabridge::Stack<T>::get (L, 1);
+ double sample_rate = luabridge::Stack<double>::get (L, 2);
+ int64_t sample = luabridge::Stack<int64_t>::get (L, 3);
+
+ Timecode::Time timecode;
+
+ Timecode::sample_to_timecode (
+ sample, timecode, false, false,
+ Timecode::timecode_to_frames_per_second (tf),
+ Timecode::timecode_has_drop_frames (tf),
+ sample_rate,
+ 0, false, 0);
+
+ luabridge::Stack<uint32_t>::push (L, timecode.hours);
+ luabridge::Stack<uint32_t>::push (L, timecode.minutes);
+ luabridge::Stack<uint32_t>::push (L, timecode.seconds);
+ luabridge::Stack<uint32_t>::push (L, timecode.frames);
+ return 4;
+}
+
+int
+ARDOUR::LuaAPI::timecode_to_sample (lua_State *L)
+{
+ int top = lua_gettop (L);
+ if (top < 6) {
+ return luaL_argerror (L, 1, "invalid number of arguments sample_to_timecode (TimecodeFormat, sample_rate, hh, mm, ss, ff)");
+ }
+ typedef Timecode::TimecodeFormat T;
+ T tf = luabridge::Stack<T>::get (L, 1);
+ double sample_rate = luabridge::Stack<double>::get (L, 2);
+ int hh = luabridge::Stack<int>::get (L, 3);
+ int mm = luabridge::Stack<int>::get (L, 4);
+ int ss = luabridge::Stack<int>::get (L, 5);
+ int ff = luabridge::Stack<int>::get (L, 6);
+
+ Timecode::Time timecode;
+ timecode.negative = false;
+ timecode.hours = hh;
+ timecode.minutes = mm;
+ timecode.seconds = ss;
+ timecode.frames = ff;
+ timecode.subframes = 0;
+ timecode.rate = Timecode::timecode_to_frames_per_second (tf);
+ timecode.drop = Timecode::timecode_has_drop_frames (tf);
+
+ int64_t sample;
+
+ Timecode::timecode_to_sample (
+ timecode, sample, false, false,
+ sample_rate, 0, false, 0);
+
+ luabridge::Stack<int64_t>::push (L, sample);
+ return 1;
+}
+
+int
+ARDOUR::LuaAPI::sample_to_timecode_lua (lua_State *L)
+{
+ int top = lua_gettop (L);
+ if (top < 2) {
+ return luaL_argerror (L, 1, "invalid number of arguments sample_to_timecode (sample)");
+ }
+ Session const* const s = luabridge::Userdata::get <Session> (L, 1, true);
+ int64_t sample = luabridge::Stack<int64_t>::get (L, 2);
+
+ Timecode::Time timecode;
+
+ Timecode::sample_to_timecode (
+ sample, timecode, false, false,
+ s->timecode_frames_per_second (),
+ s->timecode_drop_frames (),
+ s->frame_rate (),
+ 0, false, 0);
+
+ luabridge::Stack<uint32_t>::push (L, timecode.hours);
+ luabridge::Stack<uint32_t>::push (L, timecode.minutes);
+ luabridge::Stack<uint32_t>::push (L, timecode.seconds);
+ luabridge::Stack<uint32_t>::push (L, timecode.frames);
+ return 4;
+}
+int
+ARDOUR::LuaAPI::timecode_to_sample_lua (lua_State *L)
+{
+ int top = lua_gettop (L);
+ if (top < 5) {
+ return luaL_argerror (L, 1, "invalid number of arguments sample_to_timecode (hh, mm, ss, ff)");
+ }
+ Session const* const s = luabridge::Userdata::get <Session> (L, 1, true);
+ int hh = luabridge::Stack<int>::get (L, 2);
+ int mm = luabridge::Stack<int>::get (L, 3);
+ int ss = luabridge::Stack<int>::get (L, 4);
+ int ff = luabridge::Stack<int>::get (L, 5);
+
+ Timecode::Time timecode;
+ timecode.negative = false;
+ timecode.hours = hh;
+ timecode.minutes = mm;
+ timecode.seconds = ss;
+ timecode.frames = ff;
+ timecode.subframes = 0;
+ timecode.rate = s->timecode_frames_per_second ();
+ timecode.drop = s->timecode_drop_frames ();
+
+ int64_t sample;
+
+ Timecode::timecode_to_sample (
+ timecode, sample, false, false,
+ s->frame_rate (),
+ 0, false, 0);
+
+ luabridge::Stack<int64_t>::push (L, sample);
+ return 1;
+}
+
+int
ARDOUR::LuaOSC::Address::send (lua_State *L)
{
Address * const luaosc = luabridge::Userdata::get <Address> (L, 1, false);
diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc
index 4899757188..46e1d67551 100644
--- a/libs/ardour/luabindings.cc
+++ b/libs/ardour/luabindings.cc
@@ -423,6 +423,20 @@ LuaBindings::common (lua_State* L)
//.addStaticData ("ticks_per_beat", &Timecode::BBT_Time::ticks_per_beat, false)
.endClass ()
+ .beginClass <Timecode::Time> ("Time")
+ .addConstructor <void (*) (double)> ()
+ .addData ("negative", &Timecode::Time::negative)
+ .addData ("hours", &Timecode::Time::hours)
+ .addData ("minutes", &Timecode::Time::minutes)
+ .addData ("seconds", &Timecode::Time::seconds)
+ .addData ("frames", &Timecode::Time::frames)
+ .addData ("subframes", &Timecode::Time::subframes)
+ .addData ("rate", &Timecode::Time::rate)
+ .addData ("drop", &Timecode::Time::drop)
+ .endClass ()
+
+ // TODO add increment, decrement; push it into the class
+
/* libtimecode enums */
.beginNamespace ("TimecodeFormat")
.addConst ("TC23976", Timecode::TimecodeFormat(Timecode::timecode_23976))
@@ -1809,6 +1823,11 @@ LuaBindings::common (lua_State* L)
.addFunction ("route_groups", &Session::route_groups)
.addFunction ("new_route_group", &Session::new_route_group)
.addFunction ("remove_route_group", (void (Session::*)(RouteGroup*))&Session::remove_route_group)
+ .addExtCFunction ("timecode_to_sample_lua", ARDOUR::LuaAPI::timecode_to_sample_lua)
+ .addExtCFunction ("sample_to_timecode_lua", ARDOUR::LuaAPI::sample_to_timecode_lua)
+ .addFunction ("timecode_frames_per_hour", &Session::timecode_frames_per_hour)
+ .addFunction ("timecode_frames_per_second", &Session::timecode_frames_per_second)
+ .addFunction ("timecode_drop_frames", &Session::timecode_drop_frames)
.endClass ()
.beginClass <RegionFactory> ("RegionFactory")
@@ -1853,6 +1872,8 @@ LuaBindings::common (lua_State* L)
.addFunction ("usleep", Glib::usleep)
.addCFunction ("build_filename", ARDOUR::LuaAPI::build_filename)
.addFunction ("new_noteptr", ARDOUR::LuaAPI::new_noteptr)
+ .addCFunction ("sample_to_timecode", ARDOUR::LuaAPI::sample_to_timecode)
+ .addCFunction ("timecode_to_sample", ARDOUR::LuaAPI::timecode_to_sample)
.beginClass <ARDOUR::LuaAPI::Vamp> ("Vamp")
.addConstructor <void (*) (const std::string&, float)> ()