X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fluainstance.cc;h=4d3ea5f777a0e0e50fb433b05f53e8b0ac7ed7dc;hb=9c2682d6f177c485bdc5827bc1d887387ab75aeb;hp=d8ec0a20f2bcf32f37fca3b7cc02b7963619a51d;hpb=2b943ea36c128819d808087f853977fdd8e5c09d;p=ardour.git diff --git a/gtk2_ardour/luainstance.cc b/gtk2_ardour/luainstance.cc index d8ec0a20f2..4d3ea5f777 100644 --- a/gtk2_ardour/luainstance.cc +++ b/gtk2_ardour/luainstance.cc @@ -17,6 +17,8 @@ */ #include +#include +#include #include "gtkmm2ext/gui_thread.h" @@ -33,11 +35,283 @@ #include "region_selection.h" #include "luainstance.h" #include "luasignal.h" +#include "marker.h" #include "time_axis_view.h" #include "selection.h" #include "script_selector.h" +#include "utils_videotl.h" -#include "i18n.h" +#include "pbd/i18n.h" + +namespace LuaCairo { +/** wrap RefPtr< Cairo::ImageSurface > + * + * Image surfaces provide the ability to render to memory buffers either + * allocated by cairo or by the calling code. The supported image formats are + * those defined in Cairo::Format. + */ +class ImageSurface { + public: + /** + * Creates an image surface of the specified format and dimensions. Initially + * the surface contents are all 0. (Specifically, within each pixel, each + * color or alpha channel belonging to format will be 0. The contents of bits + * within a pixel, but not belonging to the given format are undefined). + * + * @param format format of pixels in the surface to create + * @param width width of the surface, in pixels + * @param height height of the surface, in pixels + */ + ImageSurface (Cairo::Format format, int width, int height) + : _surface (Cairo::ImageSurface::create (format, width, height)) + , _ctx (Cairo::Context::create (_surface)) + , ctx (_ctx->cobj ()) {} + + ~ImageSurface () {} + + /** + * Set this surface as source for another context. + * This allows to draw this surface + */ + void set_as_source (Cairo::Context* c, int x, int y) { + _surface->flush (); + c->set_source (_surface, x, y); + } + + /** + * Returns a context object to perform operations on the surface + */ + Cairo::Context* context () { + return (Cairo::Context *)&ctx; + } + + /** + * Returns the stride of the image surface in bytes (or 0 if surface is not + * an image surface). The stride is the distance in bytes from the beginning + * of one row of the image data to the beginning of the next row. + */ + int get_stride () const { + return _surface->get_stride (); + } + + /** Gets the width of the ImageSurface in pixels */ + int get_width () const { + return _surface->get_width (); + } + + /** Gets the height of the ImageSurface in pixels */ + int get_height () const { + return _surface->get_height (); + } + + /** + * Get a pointer to the data of the image surface, for direct + * inspection or modification. + * + * Return value: a pointer to the image data of this surface or NULL + * if @surface is not an image surface. + * + */ + unsigned char* get_data () { + return _surface->get_data (); + } + + /** Tells cairo to consider the data buffer dirty. + * + * In particular, if you've created an ImageSurface with a data buffer that + * you've allocated yourself and you draw to that data buffer using means + * other than cairo, you must call mark_dirty() before doing any additional + * drawing to that surface with cairo. + * + * Note that if you do draw to the Surface outside of cairo, you must call + * flush() before doing the drawing. + */ + void mark_dirty () { + _surface->mark_dirty (); + } + + /** Marks a rectangular area of the given surface dirty. + * + * @param x X coordinate of dirty rectangle + * @param y Y coordinate of dirty rectangle + * @param width width of dirty rectangle + * @param height height of dirty rectangle + */ + void mark_dirty (int x, int y, int width, int height) { + _surface->mark_dirty (x, y, width, height); + } + + private: + Cairo::RefPtr _surface; + Cairo::RefPtr _ctx; + Cairo::Context ctx; +}; + +class PangoLayout { + public: + /** Create a new PangoLayout Text Display + * @param c CairoContext for the layout + * @param font_name a font-description e.g. "Mono 8px" + */ + PangoLayout (Cairo::Context* c, std::string font_name) { + ::PangoLayout* pl = pango_cairo_create_layout (c->cobj ()); + _layout = Glib::wrap (pl); + Pango::FontDescription fd (font_name); + _layout->set_font_description (fd); + } + + ~PangoLayout () {} + + /** Gets the text in the layout. The returned text should not + * be freed or modified. + * + * @return The text in the @a layout. + */ + std::string get_text () const { + return _layout->get_text (); + } + /** Set the text of the layout. + * @param text The text for the layout. + */ + void set_text (const std::string& text) { + _layout->set_text (text); + } + + /** Sets the layout text and attribute list from marked-up text (see markup format). + * Replaces the current text and attribute list. + * @param markup Some marked-up text. + */ + void set_markup (const std::string& markup) { + _layout->set_markup (markup); + } + + /** Sets the width to which the lines of the Pango::Layout should wrap or + * ellipsized. The default value is -1: no width set. + * + * @param width The desired width in Pango units, or -1 to indicate that no + * wrapping or ellipsization should be performed. + */ + void set_width (int width) { + _layout->set_width (width * PANGO_SCALE); + } + + /** Gets the width to which the lines of the Pango::Layout should wrap. + * + * @return The width in Pango units, or -1 if no width set. + */ + int get_width () const { + return _layout->get_width () / PANGO_SCALE; + } + + /** Sets the type of ellipsization being performed for @a layout. + * Depending on the ellipsization mode @a ellipsize text is + * removed from the start, middle, or end of text so they + * fit within the width and height of layout set with + * set_width() and set_height(). + * + * If the layout contains characters such as newlines that + * force it to be layed out in multiple paragraphs, then whether + * each paragraph is ellipsized separately or the entire layout + * is ellipsized as a whole depends on the set height of the layout. + * See set_height() for details. + * + * @param ellipsize The new ellipsization mode for @a layout. + */ + void set_ellipsize (Pango::EllipsizeMode ellipsize) { + _layout->set_ellipsize (ellipsize); + } + + /** Gets the type of ellipsization being performed for @a layout. + * See set_ellipsize() + * + * @return The current ellipsization mode for @a layout. + * + * Use is_ellipsized() to query whether any paragraphs + * were actually ellipsized. + */ + Pango::EllipsizeMode get_ellipsize () const { + return _layout->get_ellipsize (); + } + + /** Queries whether the layout had to ellipsize any paragraphs. + * + * This returns true if the ellipsization mode for @a layout + * is not Pango::ELLIPSIZE_NONE, a positive width is set on @a layout, + * and there are paragraphs exceeding that width that have to be + * ellipsized. + * + * @return true if any paragraphs had to be ellipsized, false + * otherwise. + */ + bool is_ellipsized () const { + return _layout->is_ellipsized (); + } + + /** Sets the wrap mode; the wrap mode only has effect if a width + * is set on the layout with set_width(). + * To turn off wrapping, set the width to -1. + * + * @param wrap The wrap mode. + */ + void set_wrap (Pango::WrapMode wrap) { + _layout->set_width (wrap); + } + + /** Gets the wrap mode for the layout. + * + * Use is_wrapped() to query whether any paragraphs + * were actually wrapped. + * + * @return Active wrap mode. + */ + Pango::WrapMode get_wrap () const { + return _layout->get_wrap (); + } + + /** Queries whether the layout had to wrap any paragraphs. + * + * This returns true if a positive width is set on @a layout, + * ellipsization mode of @a layout is set to Pango::ELLIPSIZE_NONE, + * and there are paragraphs exceeding the layout width that have + * to be wrapped. + * + * @return true if any paragraphs had to be wrapped, false + * otherwise. + */ + bool is_wrapped () const { + return _layout->is_wrapped (); + } + + /** Determines the logical width and height of a Pango::Layout + * in device units. + */ + int get_pixel_size (lua_State *L) { + int width, height; + _layout->get_pixel_size (width, height); + luabridge::Stack::push (L, width); + luabridge::Stack::push (L, height); + return 2; + } + + + /** Draws a Layout in the specified Cairo @a context. The top-left + * corner of the Layout will be drawn at the current point of the + * cairo context. + * + * @param context A Cairo context. + */ + void show_in_cairo_context (Cairo::Context* c) { + pango_cairo_update_layout (c->cobj (), _layout->gobj()); + pango_cairo_show_layout (c->cobj (), _layout->gobj()); + } + + private: + Glib::RefPtr _layout; +}; + +}; // namespace + +//////////////////////////////////////////////////////////////////////////////// namespace LuaSignal { @@ -72,6 +346,17 @@ const char *luasignalstr[] = { #undef ENGINE }; // namespace + +std::string lua_http_get (const char *u) { + char *rv = a3_curl_http_get (u, NULL); + if (!rv) { + return ""; + } + std::string s (rv); + free (rv); + return s; +} + //////////////////////////////////////////////////////////////////////////////// #define xstr(s) stringify(s) @@ -180,6 +465,51 @@ LuaInstance::bind_cairo (lua_State* L) .addConst ("Add", CAIRO_OPERATOR_ADD) .endNamespace () + .beginNamespace ("Format") + .addConst ("ARGB32", CAIRO_FORMAT_ARGB32) + .addConst ("RGB24", CAIRO_FORMAT_RGB24) + .endNamespace () + + .beginClass ("ImageSurface") + .addConstructor () + .addFunction ("set_as_source", &LuaCairo::ImageSurface::set_as_source) + .addFunction ("context", &LuaCairo::ImageSurface::context) + .addFunction ("get_stride", &LuaCairo::ImageSurface::get_stride) + .addFunction ("get_width", &LuaCairo::ImageSurface::get_width) + .addFunction ("get_height", &LuaCairo::ImageSurface::get_height) + //.addFunction ("get_data", &LuaCairo::ImageSurface::get_data) // uint8_t* array is n/a + .endClass () + + .beginClass ("PangoLayout") + .addConstructor () + .addCFunction ("get_pixel_size", &LuaCairo::PangoLayout::get_pixel_size) + .addFunction ("get_text", &LuaCairo::PangoLayout::get_text) + .addFunction ("set_text", &LuaCairo::PangoLayout::set_text) + .addFunction ("show_in_cairo_context", &LuaCairo::PangoLayout::show_in_cairo_context) + .addFunction ("set_markup", &LuaCairo::PangoLayout::set_markup) + .addFunction ("set_width", &LuaCairo::PangoLayout::set_width) + .addFunction ("set_ellipsize", &LuaCairo::PangoLayout::set_ellipsize) + .addFunction ("get_ellipsize", &LuaCairo::PangoLayout::get_ellipsize) + .addFunction ("is_ellipsized", &LuaCairo::PangoLayout::is_ellipsized) + .addFunction ("set_wrap", &LuaCairo::PangoLayout::set_wrap) + .addFunction ("get_wrap", &LuaCairo::PangoLayout::get_wrap) + .addFunction ("is_wrapped", &LuaCairo::PangoLayout::is_wrapped) + .endClass () + + /* enums */ + .beginNamespace ("EllipsizeMode") + .addConst ("None", Pango::ELLIPSIZE_NONE) + .addConst ("Start", Pango::ELLIPSIZE_START) + .addConst ("Middle", Pango::ELLIPSIZE_MIDDLE) + .addConst ("End", Pango::ELLIPSIZE_END) + .endNamespace () + + .beginNamespace ("WrapMode") + .addConst ("Word", Pango::WRAP_WORD) + .addConst ("Char", Pango::WRAP_CHAR) + .addConst ("WordChar", Pango::WRAP_WORD_CHAR) + .endNamespace () + .endNamespace (); /* Lua/cairo bindings operate on Cairo::Context, there is no Cairo::RefPtr wrapper [yet]. @@ -218,12 +548,16 @@ LuaInstance::register_classes (lua_State* L) luabridge::getGlobalNamespace (L) .beginNamespace ("ArdourUI") - .beginClass ("RegionSelection") - .addFunction ("clear_all", &RegionSelection::clear_all) - .addFunction ("start", &RegionSelection::start) - .addFunction ("end_frame", &RegionSelection::end_frame) - .addFunction ("n_midi_regions", &RegionSelection::n_midi_regions) - .addFunction ("regionlist", &RegionSelection::regionlist) // XXX check windows binding (libardour) + + .addFunction ("curl_http_get", &lua_http_get) + + .beginStdList ("ArdourMarkerList") + .endClass () + + .beginClass ("ArdourMarker") + .addFunction ("name", &ArdourMarker::name) + .addFunction ("position", &ArdourMarker::position) + .addFunction ("_type", &ArdourMarker::type) .endClass () #if 0 @@ -235,11 +569,21 @@ LuaInstance::register_classes (lua_State* L) .endClass () #endif - .beginClass ("Selection") - .addFunction ("clear", &Selection::clear) - .addFunction ("clear_all", &Selection::clear_all) - .addData ("tracks", &Selection::tracks) - .addData ("regions", &Selection::regions) + .beginClass ("RegionSelection") + .addFunction ("clear_all", &RegionSelection::clear_all) + .addFunction ("start", &RegionSelection::start) + .addFunction ("end_frame", &RegionSelection::end_frame) + .addFunction ("n_midi_regions", &RegionSelection::n_midi_regions) + .addFunction ("regionlist", &RegionSelection::regionlist) // XXX check windows binding (libardour) + .endClass () + + .deriveClass > ("TimeSelection") + .addFunction ("start", &TimeSelection::start) + .addFunction ("end_frame", &TimeSelection::end_frame) + .addFunction ("length", &TimeSelection::length) + .endClass () + + .deriveClass > ("MarkerSelection") .endClass () .beginClass ("TrackViewList") @@ -249,7 +593,21 @@ LuaInstance::register_classes (lua_State* L) .deriveClass ("TrackSelection") .endClass () - .beginClass ("ArdourMarker") + .beginClass ("Selection") + .addFunction ("clear", &Selection::clear) + .addFunction ("clear_all", &Selection::clear_all) + .addFunction ("empty", &Selection::empty) + .addData ("tracks", &Selection::tracks) + .addData ("regions", &Selection::regions) + .addData ("time", &Selection::time) + .addData ("markers", &Selection::markers) +#if 0 + .addData ("lines", &Selection::lines) + .addData ("playlists", &Selection::playlists) + .addData ("points", &Selection::points) + .addData ("midi_regions", &Selection::midi_regions) + .addData ("midi_notes", &Selection::midi_notes) // cut buffer only +#endif .endClass () .beginClass ("Editor") @@ -396,7 +754,25 @@ LuaInstance::register_classes (lua_State* L) .addFunction ("access_action", &PublicEditor::access_action) .endClass () - .endNamespace (); + + /* ArdourUI enums */ + .beginNamespace ("MarkerType") + .addConst ("Mark", ArdourMarker::Type(ArdourMarker::Mark)) + .addConst ("Tempo", ArdourMarker::Type(ArdourMarker::Tempo)) + .addConst ("Meter", ArdourMarker::Type(ArdourMarker::Meter)) + .addConst ("SessionStart", ArdourMarker::Type(ArdourMarker::SessionStart)) + .addConst ("SessionEnd", ArdourMarker::Type(ArdourMarker::SessionEnd)) + .addConst ("RangeStart", ArdourMarker::Type(ArdourMarker::RangeStart)) + .addConst ("RangeEnd", ArdourMarker::Type(ArdourMarker::RangeEnd)) + .addConst ("LoopStart", ArdourMarker::Type(ArdourMarker::LoopStart)) + .addConst ("LoopEnd", ArdourMarker::Type(ArdourMarker::LoopEnd)) + .addConst ("PunchIn", ArdourMarker::Type(ArdourMarker::PunchIn)) + .addConst ("PunchOut", ArdourMarker::Type(ArdourMarker::PunchOut)) + .endNamespace () + + .endNamespace (); // end ArdourUI + + // Editing Symbols #undef ZOOMFOCUS #undef SNAPTYPE @@ -640,7 +1016,7 @@ LuaInstance::session_going_away () int LuaInstance::set_state (const XMLNode& node) { - LocaleGuard lg (X_("C")); + LocaleGuard lg; XMLNode* child; if ((child = find_named_node (node, "ActionScript"))) { @@ -746,7 +1122,7 @@ LuaInstance::interactive_add (LuaScriptInfo::ScriptType type, int id) XMLNode& LuaInstance::get_action_state () { - LocaleGuard lg (X_("C")); + LocaleGuard lg; std::string saved; { luabridge::LuaRef savedstate ((*_lua_save)());