titler overlay rework, clear yuv vframe
[goodguy/history.git] / cinelerra-5.1 / plugins / titler / titlerwindow.C
index d44140607b00556445ca58ebc54aac3933502b4d..82979d12783d9243cab4b9688d735ec7615918ef 100644 (file)
@@ -32,7 +32,9 @@
 #include "edlsession.h"
 #include "keys.h"
 #include "language.h"
+#include "mainerror.h"
 #include "mwindow.h"
+#include "mwindowgui.h"
 #include "plugin.h"
 #include "pluginserver.h"
 #include "theme.h"
@@ -113,6 +115,7 @@ TitleWindow::TitleWindow(TitleMain *client)
        background = 0;
        background_path = 0;
        loop_playback = 0;
+       pending_config = 0;
 }
 
 void TitleWindow::done_event(int result)
@@ -255,10 +258,13 @@ void TitleWindow::create_objects()
        int w1 = italic->get_w();
        add_tool(bold = new TitleBold(client, this, x, y + 50));
        if( bold->get_w() > w1 ) w1 = bold->get_w();
+
        add_tool(drag = new TitleDrag(client, this, x, y + 80));
        if( drag->get_w() > w1 ) w1 = drag->get_w();
-       if( client->config.drag )
-               grab(client->server->mwindow->cwindow->gui);
+       if( client->config.drag ) {
+               if( !grab(client->server->mwindow->cwindow->gui) )
+                       eprintf("drag enabled, but compositor already grabbed\n");
+       }
 
        x += w1 + margin;
        add_tool(justify_title = new BC_Title(x, y, _("Justify:")));
@@ -309,7 +315,7 @@ void TitleWindow::create_objects()
        x1 += motion_title->get_w()+margin;
        motion = new TitleMotion(client, this, x1, y);
        motion->create_objects();
-       add_tool(loop = new TitleLoop(client, x, y1));
+       add_tool(loop = new TitleLoop(client, this, x, y1));
        x = margin;    y = y1 + loop->get_h()+20;
 
        add_tool(dropshadow_title = new BC_Title(x, y, _("Drop shadow:")));
@@ -364,9 +370,9 @@ void TitleWindow::create_objects()
        x += stroker->get_w() + margin;
 #endif
        y += outline_title->get_h() + margin;
-       add_tool(timecode = new TitleTimecode(client, x1=x, y));
+       add_tool(timecode = new TitleTimecode(client, this, x1=x, y));
        x += timecode->get_w() + margin;
-       add_tool(timecode_format = new TitleTimecodeFormat(client, x, y,
+       add_tool(timecode_format = new TitleTimecodeFormat(client, this, x, y,
                Units::print_time_format(client->config.timecode_format, string)));
        timecode_format->create_objects();
        y += timecode_format->get_h() + margin;
@@ -380,7 +386,7 @@ void TitleWindow::create_objects()
                client->server->mwindow->theme, this, background_path,
                x, y, "", _("background media"), _("Select background media path")));
        x += background_browse->get_w() + 3*margin;
-       add_tool(loop_playback = new TitleLoopPlayback(client, x, y));
+       add_tool(loop_playback = new TitleLoopPlayback(client, this, x, y));
        y += loop_playback->get_h() + 10;
 
        x = 10;
@@ -463,26 +469,57 @@ int TitleWindow::resize_event(int w, int h)
        return 1;
 }
 
+void TitleWindow::send_configure_change()
+{
+       pending_config = 0;
+       client->send_configure_change();
+}
+int TitleWindow::check_configure_change(int ret)
+{
+       if( pending_config && !grab_event_count() )
+               send_configure_change();
+       return ret;
+}
+
 int TitleWindow::grab_event(XEvent *event)
 {
+       switch( event->type ) {
+       case ButtonPress: break;
+       case ButtonRelease: break;
+       case MotionNotify: break;
+       default:
+               return check_configure_change(0);
+       }
+
+       MWindow *mwindow = client->server->mwindow;
+       CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
+       CWindowCanvas *canvas = cwindow_gui->canvas;
+       int cx, cy;  cwindow_gui->get_relative_cursor(cx, cy);
+       cx -= mwindow->theme->ccanvas_x;
+       cy -= mwindow->theme->ccanvas_y;
+
+       if( !dragging ) {
+               if( cx < 0 || cx >= mwindow->theme->ccanvas_w ||
+                   cy < 0 || cy >= mwindow->theme->ccanvas_h )
+                       return check_configure_change(0);
+       }
+
        switch( event->type ) {
        case ButtonPress:
                if( !dragging ) break;
                return 1;
        case ButtonRelease:
-               if( !dragging ) return 0;
+               if( !dragging ) return check_configure_change(0);
                dragging = 0;
                return 1;
        case MotionNotify:
-               if( dragging ) break;
+               if( !dragging ) return check_configure_change(0);
+               break;
        default:
-               return 0;
+               return check_configure_change(0);
        }
-       MWindow *mwindow = client->server->mwindow;
-       CWindowGUI *cwindow_gui = mwindow->cwindow->gui;
-       CWindowCanvas *canvas = cwindow_gui->canvas;
-       float cursor_x = canvas->get_canvas()->get_relative_cursor_x();
-       float cursor_y = canvas->get_canvas()->get_relative_cursor_y();
+
+       float cursor_x = cx, cursor_y = cy;
        canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y);
        int64_t position = client->get_source_position();
        float projector_x, projector_y, projector_z;
@@ -504,7 +541,7 @@ int TitleWindow::grab_event(XEvent *event)
        int y0 = title_y, y1 = title_y+(title_h+1)/2, y2 = title_y+title_h;
        int drag_dx = 0, drag_dy = 0;
        if( !dragging ) {  // clockwise
-                    if( abs(drag_dx = cursor_x-x0) < r &&       // x0,y0
+                    if( abs(drag_dx = cursor_x-x0) < r &&  // x0,y0
                         abs(drag_dy = cursor_y-y0) < r ) dragging = 1;
                else if( abs(drag_dx = cursor_x-x1) < r &&  // x1,y0
                         abs(drag_dy = cursor_y-y0) < r ) dragging = 2;
@@ -596,7 +633,10 @@ int TitleWindow::grab_event(XEvent *event)
                this->title_y->update((int64_t)(client->config.title_y += dy));
                }
        }
-       client->send_configure_change();
+       if( !grab_event_count() )
+               send_configure_change();
+       else
+               pending_config = 1;
        return 1;
 }
 
@@ -615,7 +655,7 @@ void TitleWindow::previous_font()
        font->update(fonts.values[current_font]->get_text());
        strcpy(client->config.font, fonts.values[current_font]->get_text());
        check_style(client->config.font,1);
-       client->send_configure_change();
+       send_configure_change();
 }
 
 void  TitleWindow::next_font()
@@ -633,7 +673,7 @@ void  TitleWindow::next_font()
        font->update(fonts.values[current_font]->get_text());
        strcpy(client->config.font, fonts.values[current_font]->get_text());
        check_style(client->config.font,1);
-       client->send_configure_change();
+       send_configure_change();
 }
 
 int TitleWindow::insert_ibeam(const char *txt, int ofs)
@@ -650,7 +690,7 @@ int TitleWindow::insert_ibeam(const char *txt, int ofs)
                ibeam = client->config.wlen;
        text->wset_selection(-1, -1, ibeam);
        text->update(client->config.wtext);
-       client->send_configure_change();
+       send_configure_change();
        return 1;
 }
 
@@ -681,7 +721,7 @@ void TitleWindow::update_justification()
 void TitleWindow::update_stats()
 {
        text_chars->update(client->config.wlen);
-       int len = MESSAGESIZE-16 - strlen(text->get_text());
+       int len = MESSAGESIZE - BCTEXTLEN - strlen(text->get_text()) - 1;
        if( len < 0 ) len = 0;
        text_bfrsz->update(len);
 }
@@ -774,7 +814,7 @@ int TitleSizeTumble::handle_up_event()
 
        client->config.size = atoi(window->sizes.get(current_index)->get_text());
        window->size->update(client->config.size);
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -797,7 +837,7 @@ int TitleSizeTumble::handle_down_event()
 
        client->config.size = atoi(window->sizes.get(current_index)->get_text());
        window->size->update(client->config.size);
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -813,7 +853,7 @@ int TitleBold::handle_event()
        client->config.style =
                (client->config.style & ~BC_FONT_BOLD) |
                        (get_value() ? BC_FONT_BOLD : 0);
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -828,7 +868,7 @@ int TitleItalic::handle_event()
        client->config.style =
                (client->config.style & ~BC_FONT_ITALIC) |
                        (get_value() ? BC_FONT_ITALIC : 0);
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -847,7 +887,7 @@ int TitleSize::handle_event()
 {
        client->config.size = atol(get_text());
 //printf("TitleSize::handle_event 1 %s\n", get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 void TitleSize::update(int size)
@@ -874,7 +914,7 @@ TitlePitch::
 int TitlePitch::handle_event()
 {
        *value = atol(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -915,25 +955,27 @@ TitleMotion::TitleMotion(TitleMain *client, TitleWindow *window, int x, int y)
 int TitleMotion::handle_event()
 {
        client->config.motion_strategy = client->text_to_motion(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
-TitleLoop::TitleLoop(TitleMain *client, int x, int y)
+TitleLoop::TitleLoop(TitleMain *client, TitleWindow *window, int x, int y)
  : BC_CheckBox(x, y, client->config.loop, _("Loop"))
 {
        this->client = client;
+       this->window = window;
 }
 int TitleLoop::handle_event()
 {
        client->config.loop = get_value();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
-TitleTimecode::TitleTimecode(TitleMain *client, int x, int y)
+TitleTimecode::TitleTimecode(TitleMain *client, TitleWindow *window, int x, int y)
  : BC_CheckBox(x, y, client->config.timecode, _("Stamp timecode"))
 {
        this->client = client;
+       this->window = window;
 }
 int TitleTimecode::handle_event()
 {
@@ -942,16 +984,18 @@ int TitleTimecode::handle_event()
        return 1;
 }
 
-TitleTimecodeFormat::TitleTimecodeFormat(TitleMain *client, int x, int y, const char *text)
+TitleTimecodeFormat::TitleTimecodeFormat(TitleMain *client, TitleWindow *window,
+               int x, int y, const char *text)
  : BC_PopupMenu(x, y, 100, text, 1)
 {
        this->client = client;
+       this->window = window;
 }
 
 int TitleTimecodeFormat::handle_event()
 {
        client->config.timecode_format = Units::text_to_format(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -990,7 +1034,7 @@ TitleFade::TitleFade(TitleMain *client, TitleWindow *window,
 int TitleFade::handle_event()
 {
        *value = atof(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1036,7 +1080,7 @@ int TitleFont::handle_event()
 {
        strcpy(client->config.font, get_text());
        window->check_style(client->config.font, 1);
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1064,12 +1108,24 @@ int TitleText::button_press_event()
 int TitleText::handle_event()
 {
        window->fonts_popup->deactivate();
+       int text_len = strlen(get_text());
+       int avail = MESSAGESIZE - BCTEXTLEN;
+       if( text_len >= avail ) { // back off last utf8 char
+               char text[2*sizeof(client->config.wtext)];
+               strcpy(text, get_text());
+               text_len = avail;
+               while( text_len > 0 && (text[text_len-1] & 0xc0) == 0x80 )
+                       text[--text_len] = 0;
+               if( text_len > 0 )
+                       text[--text_len] = 0;
+               update(text);
+       }
        int len =  sizeof(client->config.wtext) / sizeof(wchar_t);
        wcsncpy(client->config.wtext, get_wtext(), len);
        client->config.wtext[len-1] = 0;
        client->config.wlen = wcslen(client->config.wtext);
        window->update_stats();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 TitleTextChars::TitleTextChars(int x, int y, int w)
@@ -1102,8 +1158,8 @@ int TitleTextBfrSz::update(int n)
 
 
 TitleDropShadow::TitleDropShadow(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (int64_t)client->config.dropshadow,
-       (int64_t)-1000, (int64_t)1000, x, y, 70)
+ : BC_TumbleTextBox(window, client->config.dropshadow,
+               -1000, 1000, x, y, 70)
 {
        this->client = client;
        this->window = window;
@@ -1111,32 +1167,34 @@ TitleDropShadow::TitleDropShadow(TitleMain *client, TitleWindow *window, int x,
 int TitleDropShadow::handle_event()
 {
        client->config.dropshadow = atol(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
 
 TitleOutline::TitleOutline(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (int64_t)client->config.outline_size,
-       (int64_t)0, (int64_t)1000, x, y, 70)
+ : BC_TumbleTextBox(window, client->config.outline_size,
+               0.f, 1000.f, x, y, 70)
 {
        this->client = client;
        this->window = window;
+       set_precision(1);
 }
 int TitleOutline::handle_event()
 {
-       client->config.outline_size = atol(get_text());
-       client->send_configure_change();
+       client->config.outline_size = atof(get_text());
+       window->send_configure_change();
        return 1;
 }
 
 
 TitleStroker::TitleStroker(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (int64_t)client->config.stroke_width,
-       (int64_t)0, (int64_t)1000, x, y, 70)
+ : BC_TumbleTextBox(window, client->config.stroke_width,
+               0.f, 1000.f, x, y, 70)
 {
        this->client = client;
        this->window = window;
+       set_precision(1);
 }
 int TitleStroker::handle_event()
 {
@@ -1145,42 +1203,44 @@ int TitleStroker::handle_event()
                client->config.style |= BC_FONT_OUTLINE;
        else
                client->config.style &= ~BC_FONT_OUTLINE;
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
 
 TitleX::TitleX(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (int64_t)client->config.title_x,
-       (int64_t)-32767, (int64_t)32767, x, y, 50)
+ : BC_TumbleTextBox(window, client->config.title_x,
+               -32767.f, 32767.f, x, y, 50)
 {
        this->client = client;
        this->window = window;
+       set_precision(1);
 }
 int TitleX::handle_event()
 {
-       client->config.title_x = atol(get_text());
-       client->send_configure_change();
+       client->config.title_x = atof(get_text());
+       window->send_configure_change();
        return 1;
 }
 
 TitleY::TitleY(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (int64_t)client->config.title_y,
-       (int64_t)-32767, (int64_t)32767, x, y, 50)
+ : BC_TumbleTextBox(window, client->config.title_y,
+               -32767.f, 32767.f, x, y, 50)
 {
        this->client = client;
        this->window = window;
+       set_precision(1);
 }
 int TitleY::handle_event()
 {
-       client->config.title_y = atol(get_text());
-       client->send_configure_change();
+       client->config.title_y = atof(get_text());
+       window->send_configure_change();
        return 1;
 }
 
 TitleW::TitleW(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (int64_t)client->config.title_w,
-       (int64_t)0, (int64_t)32767, x, y, 50)
+ : BC_TumbleTextBox(window, client->config.title_w,
+               0, 32767, x, y, 50)
 {
        this->client = client;
        this->window = window;
@@ -1188,13 +1248,13 @@ TitleW::TitleW(TitleMain *client, TitleWindow *window, int x, int y)
 int TitleW::handle_event()
 {
        client->config.title_w = atol(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
 TitleH::TitleH(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (int64_t)client->config.title_h,
-       (int64_t)0, (int64_t)32767, x, y, 50)
+ : BC_TumbleTextBox(window, client->config.title_h,
+               0, 32767, x, y, 50)
 {
        this->client = client;
        this->window = window;
@@ -1202,15 +1262,16 @@ TitleH::TitleH(TitleMain *client, TitleWindow *window, int x, int y)
 int TitleH::handle_event()
 {
        client->config.title_h = atol(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
 TitleSpeed::TitleSpeed(TitleMain *client, TitleWindow *window, int x, int y)
- : BC_TumbleTextBox(window, (float)client->config.pixels_per_second,
-       (float)0, (float)1000, x, y, 100)
+ : BC_TumbleTextBox(window, client->config.pixels_per_second,
+               0.f, 1000.f, x, y, 100)
 {
        this->client = client;
+       this->window = window;
        set_precision(2);
        set_increment(10);
 }
@@ -1219,7 +1280,7 @@ TitleSpeed::TitleSpeed(TitleMain *client, TitleWindow *window, int x, int y)
 int TitleSpeed::handle_event()
 {
        client->config.pixels_per_second = atof(get_text());
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1234,7 +1295,7 @@ int TitleLeft::handle_event()
 {
        client->config.hjustification = JUSTIFY_LEFT;
        window->update_justification();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1248,7 +1309,7 @@ int TitleCenter::handle_event()
 {
        client->config.hjustification = JUSTIFY_CENTER;
        window->update_justification();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1262,7 +1323,7 @@ int TitleRight::handle_event()
 {
        client->config.hjustification = JUSTIFY_RIGHT;
        window->update_justification();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1278,7 +1339,7 @@ int TitleTop::handle_event()
 {
        client->config.vjustification = JUSTIFY_TOP;
        window->update_justification();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1292,7 +1353,7 @@ int TitleMid::handle_event()
 {
        client->config.vjustification = JUSTIFY_MID;
        window->update_justification();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1306,7 +1367,7 @@ int TitleBottom::handle_event()
 {
        client->config.vjustification = JUSTIFY_BOTTOM;
        window->update_justification();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1336,7 +1397,7 @@ int TitleColorThread::handle_new_color(int output, int alpha)
        window->flush();
        window->unlock_window();
 
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1350,12 +1411,17 @@ TitleDrag::TitleDrag(TitleMain *client, TitleWindow *window, int x, int y)
 int TitleDrag::handle_event()
 {
        int value = get_value();
-       client->config.drag = value;
-       if( value )
-               window->grab(client->server->mwindow->cwindow->gui);
+       CWindowGUI *cwindow_gui = client->server->mwindow->cwindow->gui;
+       if( value ) {
+               if( !window->grab(cwindow_gui) ) {
+                       update(value = 0);
+                       flicker(10,50);
+               }
+       }
        else
-               window->ungrab(client->server->mwindow->cwindow->gui);
-       client->send_configure_change();
+               window->ungrab(cwindow_gui);
+       client->config.drag = value;
+       window->send_configure_change();
        return 1;
 }
 
@@ -1369,7 +1435,7 @@ TitleBackground::TitleBackground(TitleMain *client, TitleWindow *window, int x,
 int TitleBackground::handle_event()
 {
        client->config.background = get_value();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1383,19 +1449,20 @@ TitleBackgroundPath::TitleBackgroundPath(TitleMain *client, TitleWindow *window,
 int TitleBackgroundPath::handle_event()
 {
        strncpy(client->config.background_path, get_text(), sizeof(client->config.background_path));
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
-TitleLoopPlayback::TitleLoopPlayback(TitleMain *client, int x, int y)
+TitleLoopPlayback::TitleLoopPlayback(TitleMain *client, TitleWindow *window, int x, int y)
  : BC_CheckBox(x, y, client->config.loop_playback, _("Loop playback"))
 {
        this->client = client;
+       this->window = window;
 }
 int TitleLoopPlayback::handle_event()
 {
        client->config.loop_playback = get_value();
-       client->send_configure_change();
+       window->send_configure_change();
        return 1;
 }
 
@@ -1411,7 +1478,7 @@ int TitleCurPopup::handle_event()
        return 1;
 }
 
-void TitleCurSubMenu::add_subitem(int popup_type, va_list ap, const char *fmt)
+void TitleCurSubMenu::add_subitemx(int popup_type, va_list ap, const char *fmt)
 {
        char item[BCSTRLEN];
        vsnprintf(item, sizeof(item)-1, fmt, ap);
@@ -1533,7 +1600,7 @@ int TitleCurSubMenuItem::handle_event()
        switch( popup_type ) {
        case POPUP_FONT: {
                int px, py;
-               window->get_pop_cursor_xy(px ,py);
+               window->get_pop_cursor(px ,py);
                window->fonts_popup->activate(px, py, 300,200);
                return 1; }
        case POPUP_COLOR: {
@@ -1636,13 +1703,12 @@ void TitlePngPopup::handle_done_event(int result)
 
 BC_Window *TitlePngPopup::new_gui()
 {
-        BC_DisplayInfo display_info;
-        int x = display_info.get_abs_cursor_x();
-        int y = display_info.get_abs_cursor_y();
+       MWindow *mwindow = client->server->mwindow;
+       int x, y;  mwindow->gui->get_abs_cursor(x, y);
 
-       BC_Window *gui = new BrowseButtonWindow(client->server->mwindow->theme,
+       BC_Window *gui = new BrowseButtonWindow(mwindow->theme,
                x-25, y-100, window, "", _("Png file"), _("Png path"), 0);
-        gui->create_objects();
+       gui->create_objects();
        return gui;
 }