add stacked edl editing, add sketcher/vframe line anti-aliasing
authorGood Guy <[email protected]>
Wed, 25 Dec 2019 02:48:44 +0000 (19:48 -0700)
committerGood Guy <[email protected]>
Wed, 25 Dec 2019 02:48:44 +0000 (19:48 -0700)
fix amodule arender infinite loop for nested silence, es.po tweaks
colorpicker gadget grab fixes for foreground plugin, eye dropper fixes
fix mixer close window, tracer layout tweaks, add 9 ffmpeg formats olaf

49 files changed:
cinelerra-5.1/cinelerra/amodule.C
cinelerra-5.1/cinelerra/assetpopup.C
cinelerra-5.1/cinelerra/assetpopup.h
cinelerra-5.1/cinelerra/assetpopup.inc
cinelerra-5.1/cinelerra/cachebase.C
cinelerra-5.1/cinelerra/cachebase.h
cinelerra-5.1/cinelerra/clippopup.C
cinelerra-5.1/cinelerra/clippopup.h
cinelerra-5.1/cinelerra/clippopup.inc
cinelerra-5.1/cinelerra/colorpicker.C
cinelerra-5.1/cinelerra/colorpicker.h
cinelerra-5.1/cinelerra/cwindowgui.C
cinelerra-5.1/cinelerra/cwindowtool.C
cinelerra-5.1/cinelerra/edl.C
cinelerra-5.1/cinelerra/edl.h
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/mwindow.h
cinelerra-5.1/cinelerra/mwindowedit.C
cinelerra-5.1/cinelerra/mwindowgui.C
cinelerra-5.1/cinelerra/mwindowgui.h
cinelerra-5.1/cinelerra/preferences.inc
cinelerra-5.1/cinelerra/resourcethread.C
cinelerra-5.1/cinelerra/theme.C
cinelerra-5.1/cinelerra/theme.h
cinelerra-5.1/cinelerra/zwindow.C
cinelerra-5.1/cinelerra/zwindow.h
cinelerra-5.1/cinelerra/zwindowgui.C
cinelerra-5.1/ffmpeg/audio/user_s16le.mka [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s16le.mkv [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s16le.w64 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s24le-2.mkv [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s24le.mka [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s24le.w64 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s32le.mka [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s32le.mkv [new file with mode: 0644]
cinelerra-5.1/ffmpeg/audio/user_s32le.w64 [new file with mode: 0644]
cinelerra-5.1/guicast/bcbutton.C
cinelerra-5.1/guicast/bcbutton.h
cinelerra-5.1/guicast/bcwindowbase.C
cinelerra-5.1/guicast/test3.C
cinelerra-5.1/guicast/vframe.C
cinelerra-5.1/guicast/vframe.h
cinelerra-5.1/plugins/foreground/foreground.h
cinelerra-5.1/plugins/sketcher/sketcher.C
cinelerra-5.1/plugins/sketcher/sketcher.h
cinelerra-5.1/plugins/sketcher/sketcherwindow.C
cinelerra-5.1/plugins/sketcher/sketcherwindow.h
cinelerra-5.1/plugins/tracer/tracerwindow.C
cinelerra-5.1/po/es.po

index 9e2c59b6840a0ea98559c95813ec9818ff78fc16..fb102c5cf703d7ebbdc25fd66f9bf8075659382f 100644 (file)
@@ -295,6 +295,8 @@ int AModule::import_samples(AEdit *edit,
                nested_renderengine->command->command = command;
                result = 0;
        }
+       if( edit_sample_rate <= 0 )
+               result = 1;
 
        if( !result ) {
 // speed_buffer is (have_speed ? speed_temp : buffer)
index 156d86ab7ba84d520ac3bafa2bfd428a64c9eec3..d8142f02606b69a93f8c47de21974fdae712b72a 100644 (file)
@@ -76,13 +76,15 @@ void AssetPopup::create_objects()
        BC_SubMenu *submenu;
        add_item(info = new AssetPopupInfo(mwindow, this));
        add_item(format = new AWindowListFormat(mwindow, gui));
-       add_item(new AssetPopupSort(mwindow, this));
+       add_item(open_edl = new AssetPopupOpenEDL(mwindow, this));
+       add_item(to_clip = new AssetPopupToClip(mwindow, this));
+       add_item(sort = new AssetPopupSort(mwindow, this));
        add_item(index = new AssetPopupBuildIndex(mwindow, this));
        add_item(view = new AssetPopupView(mwindow, this));
        add_item(view_window = new AssetPopupViewWindow(mwindow, this));
        add_item(open_mixer = new AssetPopupOpenMixer(mwindow, this));
        add_item(insert_mixer = new AssetPopupInsertMixer(mwindow, this));
-       add_item(new AssetPopupPaste(mwindow, this));
+       add_item(paste = new AssetPopupPaste(mwindow, this));
        add_item(menu_item = new BC_MenuItem(_("Match...")));
        menu_item->add_submenu(submenu = new BC_SubMenu());
        submenu->add_submenuitem(new AssetMatchSize(mwindow, this));
@@ -179,6 +181,51 @@ int AssetPopupInfo::handle_event()
 }
 
 
+AssetPopupOpenEDL::AssetPopupOpenEDL(MWindow *mwindow, AssetPopup *popup)
+ : BC_MenuItem(_("Open EDL"))
+{
+       this->mwindow = mwindow;
+       this->popup = popup;
+}
+AssetPopupOpenEDL::~AssetPopupOpenEDL()
+{
+}
+
+int AssetPopupOpenEDL::handle_event()
+{
+       int assets_total = mwindow->session->drag_assets->size();
+       if( assets_total ) {
+               popup->unlock_window();
+               Indexable *idxbl = mwindow->session->drag_assets->get(0);
+               EDL *edl = idxbl && !idxbl->is_asset ? (EDL *)idxbl : 0;
+               if( edl )
+                       mwindow->stack_push(edl);
+               else
+                       eprintf(_("media is not EDL:\n%s"), idxbl->path);
+               popup->lock_window("AssetPopupOpenEDL::handle_event");
+       }
+       return 1;
+}
+
+
+AssetPopupToClip::AssetPopupToClip(MWindow *mwindow, AssetPopup *popup)
+ : BC_MenuItem(_("EDL to clip"))
+{
+       this->mwindow = mwindow;
+       this->popup = popup;
+}
+
+AssetPopupToClip::~AssetPopupToClip()
+{
+}
+
+int AssetPopupToClip::handle_event()
+{
+       mwindow->media_to_clip();
+       return 1;
+}
+
+
 AssetPopupBuildIndex::AssetPopupBuildIndex(MWindow *mwindow, AssetPopup *popup)
  : BC_MenuItem(_("Rebuild index"))
 {
index eea5a8eacb6019f2718ff0b75e5c2548ee73152c..22624e474bc0bc83633ad00d90f4e6939108cb2d 100644 (file)
@@ -51,12 +51,16 @@ public:
 
 
        AssetPopupInfo *info;
+       AWindowListFormat *format;
+       AssetPopupOpenEDL *open_edl;
+       AssetPopupToClip *to_clip;
+       AssetPopupSort *sort;
        AssetPopupBuildIndex *index;
        AssetPopupView *view;
        AssetPopupViewWindow *view_window;
        AssetPopupOpenMixer *open_mixer;
        AssetPopupInsertMixer *insert_mixer;
-       AWindowListFormat *format;
+       AssetPopupPaste *paste;
 };
 
 class AssetPopupInfo : public BC_MenuItem
@@ -72,6 +76,30 @@ public:
        AssetPopup *popup;
 };
 
+class AssetPopupOpenEDL : public BC_MenuItem
+{
+public:
+       AssetPopupOpenEDL(MWindow *mwindow, AssetPopup *popup);
+       ~AssetPopupOpenEDL();
+
+       int handle_event();
+
+       MWindow *mwindow;
+       AssetPopup *popup;
+};
+
+class AssetPopupToClip : public BC_MenuItem
+{
+public:
+       AssetPopupToClip(MWindow *mwindow, AssetPopup *popup);
+       ~AssetPopupToClip();
+
+       int handle_event();
+
+       MWindow *mwindow;
+       AssetPopup *popup;
+};
+
 class AssetPopupSort : public BC_MenuItem
 {
 public:
index 4cdb174c59728bd6b248c6ad297f22ff5706fa8a..096c729b6dd10860617aaaed4df8d090caba525b 100644 (file)
@@ -34,6 +34,8 @@
 
 class AssetPopup;
 class AssetPopupInfo;
+class AssetPopupOpenEDL;
+class AssetPopupToClip;
 class AssetPopupSort;
 class AssetPopupBuildIndex;
 class AssetPopupView;
index 40b1e1bf8d08b22dadac577f04ba56b8203891dc..690129603258dbaf37bfa5495cd89d42089251fe 100644 (file)
@@ -88,20 +88,26 @@ void CacheBase::remove_all()
 }
 
 
-void CacheBase::remove_asset(Asset *asset)
+void CacheBase::remove_item(int source_id, char *path)
 {
        CacheItemBase *current, *next;
        lock->lock("CacheBase::remove_id");
        for( current=first; current; current=next ) {
                next = current->next;
-               if( (current->path && !strcmp(current->path, asset->path)) ||
-                       current->source_id == asset->id)
+               if( current->source_id == source_id ||
+                   (path && current->path && !strcmp(current->path, path)) )
                        del_item(current);
        }
        lock->unlock();
-//printf("CacheBase::remove_asset: removed %d entries for %s\n", total, asset->path);
 }
-
+void CacheBase::remove_item(Indexable *idxbl)
+{
+       remove_item(idxbl->id, idxbl->path);
+}
+void CacheBase::remove_asset(Asset *asset)
+{
+       remove_item(asset);
+}
 
 void CacheBase::del_item(CacheItemBase *item)
 {
index a548891abede571876ac2e51efd0d36d474b2180..e87916429b58a401657fa966ee0c257a8ffd4b32 100644 (file)
@@ -73,7 +73,9 @@ public:
 // Delete item.
        void del_item(CacheItemBase *item);
        int delete_item(CacheItemBase *item);
-// Remove all items with the asset id.
+// Remove all items with the same source_id or matching path if set
+       void remove_item(int source_id, char *path);
+       void remove_item(Indexable *idxbl);
        void remove_asset(Asset *asset);
 // Called when done with the item returned by get_.
 // Ignore if item was 0.
index c9151e67b03d8516b446f4a2aeef821cb0cc1c67..c38efd99d71584d035c451b8ef6453c197463638 100644 (file)
@@ -65,13 +65,13 @@ void ClipPopup::create_objects()
        BC_SubMenu *submenu;
        add_item(info = new ClipPopupInfo(mwindow, this));
        add_item(format = new AWindowListFormat(mwindow, gui));
-       add_item(new ClipPopupSort(mwindow, this));
+       add_item(sort = new ClipPopupSort(mwindow, this));
+       add_item(open_edl = new ClipPopupOpenEDL(mwindow, this));
+       add_item(to_media = new ClipPopupToMedia(mwindow, this));
        add_item(view = new ClipPopupView(mwindow, this));
        add_item(view_window = new ClipPopupViewWindow(mwindow, this));
-       add_item(new ClipPopupCopy(mwindow, this));
-       add_item(new ClipPopupNest(mwindow, this));
-       add_item(new ClipPopupUnNest(mwindow, this));
-       add_item(new ClipPopupPaste(mwindow, this));
+       add_item(copy = new ClipPopupCopy(mwindow, this));
+       add_item(paste = new ClipPopupPaste(mwindow, this));
        add_item(menu_item = new BC_MenuItem(_("Match...")));
        menu_item->add_submenu(submenu = new BC_SubMenu());
        submenu->add_submenuitem(new ClipMatchSize(mwindow, this));
@@ -417,107 +417,46 @@ void ClipListMenu::update()
 }
 
 
-ClipPopupNest::ClipPopupNest(MWindow *mwindow, ClipPopup *popup)
- : BC_MenuItem(_("Nest"))
+ClipPopupToMedia::ClipPopupToMedia(MWindow *mwindow, ClipPopup *popup)
+ : BC_MenuItem(_("Nest to Media"))
 {
        this->mwindow = mwindow;
        this->popup = popup;
 }
-ClipPopupNest::~ClipPopupNest()
+ClipPopupToMedia::~ClipPopupToMedia()
 {
 }
 
-int ClipPopupNest::handle_event()
+int ClipPopupToMedia::handle_event()
 {
-       MWindowGUI *gui = mwindow->gui;
-       gui->lock_window("ClipPopupNest::handle_event 1");
-       if( mwindow->edl->session->proxy_scale != 1 ) {
+       if( mwindow->edl->session->proxy_scale == 1 )
+               mwindow->clip_to_media();
+       else
                eprintf("Nesting not allowed when proxy scale != 1");
-               return 1;
-       }
-       int clips_total = mwindow->session->drag_clips->total;
-       for( int i=0; i<clips_total; ++i ) {
-               EDL *edl = mwindow->edl;
-               time_t dt;      time(&dt);
-               struct tm dtm;  localtime_r(&dt, &dtm);
-               char path[BCSTRLEN];
-               sprintf(path, _("Nested_%02d%02d%02d-%02d%02d%02d"),
-                       dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
-                       dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
-               EDL *clip = mwindow->session->drag_clips->values[i];
-               EDL *nested = edl->new_nested(clip, path);
-               EDL *new_clip = edl->create_nested_clip(nested);
-               new_clip->folder_no = AW_CLIP_FOLDER;
-               sprintf(new_clip->local_session->clip_icon,
-                       "clip_%02d%02d%02d-%02d%02d%02d.png",
-                       dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
-                       dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
-               snprintf(new_clip->local_session->clip_title,
-                       sizeof(new_clip->local_session->clip_title),
-                       _("Nested: %s"), clip->local_session->clip_title);
-               strcpy(new_clip->local_session->clip_notes,
-               clip->local_session->clip_notes);
-               int idx = edl->clips.number_of(clip);
-               if( idx >= 0 ) {
-                       edl->clips[idx] = new_clip;
-                       clip->remove_user();
-               }
-               else
-                       edl->clips.append(new_clip);
-               mwindow->mainindexes->add_next_asset(0, nested);
-       }
-       mwindow->mainindexes->start_build();
-       popup->gui->async_update_assets();
-       gui->unlock_window();
        return 1;
 }
 
 
-ClipPopupUnNest::ClipPopupUnNest(MWindow *mwindow, ClipPopup *popup)
- : BC_MenuItem(_("UnNest"))
+ClipPopupOpenEDL::ClipPopupOpenEDL(MWindow *mwindow, ClipPopup *popup)
+ : BC_MenuItem(_("Open EDL"))
 {
        this->mwindow = mwindow;
        this->popup = popup;
 }
-ClipPopupUnNest::~ClipPopupUnNest()
+
+ClipPopupOpenEDL::~ClipPopupOpenEDL()
 {
 }
 
-int ClipPopupUnNest::handle_event()
+int ClipPopupOpenEDL::handle_event()
 {
-       EDL *nested_edl = 0;
-       MWindowGUI *gui = mwindow->gui;
-       gui->lock_window("ClipPopupUnNest::handle_event 1");
        int clips_total = mwindow->session->drag_clips->total;
-       for( int i=0; i<clips_total; ++i ) {
-               EDL *clip = mwindow->session->drag_clips->values[i];
-               Track *track = clip->tracks->first;
-               Edit *edit = track ? track->edits->first : 0;
-               nested_edl = edit && !edit->next && !edit->asset ? edit->nested_edl : 0;
-               while( nested_edl && (track=track->next)!=0 ) {
-                       Edit *edit = track->edits->first;
-                       if( !edit || edit->next ||
-                           ( edit->nested_edl != nested_edl &&
-                             strcmp(edit->nested_edl->path, nested_edl->path) ) )
-                               nested_edl = 0;
-               }
-               if( nested_edl ) {
-                       EDL *edl = mwindow->edl;
-                       EDL *new_clip = new EDL(edl);
-                       new_clip->create_objects();
-                       new_clip->copy_all(nested_edl);
-                       new_clip->folder_no = AW_CLIP_FOLDER;
-                       int idx = edl->clips.number_of(clip);
-                       if( idx >= 0 ) {
-                               edl->clips[idx] = new_clip;
-                               clip->remove_user();
-                       }
-                       else
-                               edl->clips.append(new_clip);
-                       popup->gui->async_update_assets();
-               }
+       if( clips_total ) {
+               popup->unlock_window();
+               EDL *clip = mwindow->session->drag_clips->values[0];
+               mwindow->stack_push(clip);
+               popup->lock_window("ClipPopupOpenEDL::handle_event");
        }
-       gui->unlock_window();
        return 1;
 }
 
index dba9eab45b9c3ee71c41bf90331e6db120ee5df6..c09508aacf0b9bf28b675464442d10627245bf00 100644 (file)
@@ -51,9 +51,14 @@ public:
 
 
        ClipPopupInfo *info;
+       AWindowListFormat *format;
+       ClipPopupSort *sort;
+       ClipPopupOpenEDL *open_edl;
        ClipPopupView *view;
        ClipPopupViewWindow *view_window;
-       AWindowListFormat *format;
+       ClipPopupCopy *copy;
+       ClipPopupToMedia *to_media;
+       ClipPopupPaste *paste;
 };
 
 class ClipPopupInfo : public BC_MenuItem
@@ -208,11 +213,11 @@ public:
        AWindowGUI *gui;
 };
 
-class ClipPopupNest : public BC_MenuItem
+class ClipPopupToMedia : public BC_MenuItem
 {
 public:
-       ClipPopupNest(MWindow *mwindow, ClipPopup *popup);
-       ~ClipPopupNest();
+       ClipPopupToMedia(MWindow *mwindow, ClipPopup *popup);
+       ~ClipPopupToMedia();
 
        int handle_event();
 
@@ -220,11 +225,11 @@ public:
        ClipPopup *popup;
 };
 
-class ClipPopupUnNest : public BC_MenuItem
+class ClipPopupOpenEDL : public BC_MenuItem
 {
 public:
-       ClipPopupUnNest(MWindow *mwindow, ClipPopup *popup);
-       ~ClipPopupUnNest();
+       ClipPopupOpenEDL(MWindow *mwindow, ClipPopup *popup);
+       ~ClipPopupOpenEDL();
 
        int handle_event();
 
index 365d47259bc4ac39b0e858bda2fb6dd24d6770cb..21399eaf613eba3a2239321deb37407efc7e356e 100644 (file)
@@ -32,10 +32,11 @@ class ClipPopupPaste;
 class ClipMatchSize;
 class ClipMatchRate;
 class ClipMatchAll;
-class ClipPopupProjectRemove;
-class ClipPopupDiskRemove;
+class ClipPopupDelete;
 class ClipPasteToFolder;
-class ClipListMenu;
 class ClipListFormat;
+class ClipListMenu;
+class ClipPopupToMedia;
+class ClipPopupOpenEDL;
 
 #endif
index 78f1f957fd2ef72b20b6c70859d9b3fde2a47491..26451d7086a68bf2ef968efe6e71113f8d4d6ac1 100644 (file)
@@ -79,7 +79,7 @@ BC_Window* ColorPicker::new_gui()
        int w = ColorWindow::calculate_w();
        int h = ColorWindow::calculate_h();
        if( ok_cancel )
-               h += bmax(BC_OKButton::calculate_h(),BC_CancelButton::calculate_h());
+               h += bmax(ColorOK::calculate_h(),ColorCancel::calculate_h());
        int root_w = display_info.get_root_w(), root_h = display_info.get_root_h();
        if( x+w > root_w ) x = root_w - w;
        if( y+h > root_h ) y = root_h - h;
@@ -266,8 +266,8 @@ void ColorGUI::create_objects()
                aph_a->create_objects();  aph_a->set_tooltip(_("Alpha"));
        }
        if( ok_cancel ) {
-               add_tool(new BC_OKButton(window));
-               add_tool(new BC_CancelButton(window));
+               add_tool(new ColorOK(this, window));
+               add_tool(new ColorCancel(this, window));
        }
        create_objects(this);
 
@@ -289,8 +289,41 @@ void ColorGUI::change_values()
 }
 
 
+ColorOK::ColorOK(ColorGUI *gui, BC_WindowBase *window)
+ : BC_OKButton(window)
+{
+       this->gui = gui;
+       this->window = window;
+}
+int ColorOK::handle_event()
+{
+       gui->ok_cancel = 0;
+       gui->close_gui();
+       window->sync_display();
+       return 1;
+}
+
+ColorCancel::ColorCancel(ColorGUI *gui, BC_WindowBase *window)
+ : BC_CancelButton(window)
+{
+       this->gui = gui;
+       this->window = window;
+}
+int ColorCancel::handle_event()
+{
+       gui->ok_cancel = 1;
+       gui->close_gui();
+       window->sync_display();
+       return 1;
+}
+
 int ColorGUI::close_gui()
 {
+       if( button_grabbed ) {
+               button_grabbed = 0;
+               window->ungrab_buttons();
+               window->ungrab_cursor();
+       }
        window->set_done(ok_cancel ? 1 : 0);
        return 1;
 }
@@ -1141,7 +1174,7 @@ int PaletteGrabButton::handle_event()
        if( gui->window->grab_buttons() ) {
                gui->window->grab_cursor();
                gui->button_grabbed = 1;
-               gui->button_press_gui(); // redraw face HI
+               return BC_Button::button_press_event(); // redraw face HI
        }
        return 1;
 }
index 85fa706b2dff8cbddc4821cb03e683deb31a9050..706b279249dbcf0f53ee261b0655c4446f389c0b 100644 (file)
@@ -151,6 +151,25 @@ public:
        ColorPicker *thread;
 };
 
+class ColorOK : public BC_OKButton
+{
+public:
+       ColorOK(ColorGUI *gui, BC_WindowBase *window);
+       int handle_event();
+
+       BC_WindowBase *window;
+       ColorGUI *gui;
+};
+
+class ColorCancel : public BC_CancelButton
+{
+public:
+       ColorCancel(ColorGUI *gui, BC_WindowBase *window);
+       int handle_event();
+
+       BC_WindowBase *window;
+       ColorGUI *gui;
+};
 
 class PaletteWheel : public BC_SubWindow
 {
index 970cadf9d9574ba66e9f861e05c3fed5fae61844..052a713d9a3eb5d831c7666ea464c15829a600c6 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "automation.h"
 #include "autos.h"
+#include "bccolors.h"
 #include "bcsignals.h"
 #include "canvas.h"
 #include "clip.h"
@@ -2345,45 +2346,22 @@ int CWindowCanvas::do_eyedrop(int &rerender, int button_press, int draw)
                                gui->eyedrop_visible = 1;
                        }
 
-// Decompression coefficients straight out of jpeglib
-#define V_TO_R    1.40200
-#define V_TO_G    -0.71414
-
-#define U_TO_G    -0.34414
-#define U_TO_B    1.77200
-
-#define GET_COLOR(type, components, max, do_yuv) \
-{ \
+#define GET_COLOR(type, components, max, do_yuv) { \
        type *row = (type*)(refresh_frame->get_rows()[i]) + \
                j * components; \
        float red = (float)*row++ / max; \
        float green = (float)*row++ / max; \
        float blue = (float)*row++ / max; \
        if( do_yuv ) \
-       { \
-               float r = red + V_TO_R * (blue - 0.5); \
-               float g = red + U_TO_G * (green - 0.5) + V_TO_G * (blue - 0.5); \
-               float b = red + U_TO_B * (green - 0.5); \
-               mwindow->edl->local_session->red += r; \
-               mwindow->edl->local_session->green += g; \
-               mwindow->edl->local_session->blue += b; \
-               if( r > mwindow->edl->local_session->red_max ) mwindow->edl->local_session->red_max = r; \
-               if( g > mwindow->edl->local_session->green_max ) mwindow->edl->local_session->green_max = g; \
-               if( b > mwindow->edl->local_session->blue_max ) mwindow->edl->local_session->blue_max = b; \
-       } \
-       else \
-       { \
-               mwindow->edl->local_session->red += red; \
-               mwindow->edl->local_session->green += green; \
-               mwindow->edl->local_session->blue += blue; \
-               if( red > mwindow->edl->local_session->red_max ) mwindow->edl->local_session->red_max = red; \
-               if( green > mwindow->edl->local_session->green_max ) mwindow->edl->local_session->green_max = green; \
-               if( blue > mwindow->edl->local_session->blue_max ) mwindow->edl->local_session->blue_max = blue; \
-       } \
+               YUV::yuv.yuv_to_rgb_f(red, green, blue, red, green-0.5, blue-0.5); \
+       mwindow->edl->local_session->red += red; \
+       mwindow->edl->local_session->green += green; \
+       mwindow->edl->local_session->blue += blue; \
+       if( red > mwindow->edl->local_session->red_max ) mwindow->edl->local_session->red_max = red; \
+       if( green > mwindow->edl->local_session->green_max ) mwindow->edl->local_session->green_max = green; \
+       if( blue > mwindow->edl->local_session->blue_max ) mwindow->edl->local_session->blue_max = blue; \
 }
 
-
-
                        mwindow->edl->local_session->red = 0;
                        mwindow->edl->local_session->green = 0;
                        mwindow->edl->local_session->blue = 0;
index 64c3c78e4fea9b1b4b3f3e59331645774c37fb0c..2f284b10be9397fa76b0a4a6f2088a1e1606f6ea 100644 (file)
@@ -636,8 +636,8 @@ void CWindowEyedropGUI::update()
        float y, u, v;
        YUV::yuv.rgb_to_yuv_f(r, g, b, y, u, v);
        this->y->update(y);
-       this->u->update(u);  u += 0.5;
-       this->v->update(v);  v += 0.5;
+       this->u->update(u += 0.5);
+       this->v->update(v += 0.5);
 
        int yx = 255*y + 0.5;  bclamp(yx,0,255);
        int ux = 255*u + 0.5;  bclamp(ux,0,255);
@@ -3082,7 +3082,7 @@ int CWindowMaskGUI::save_mask(const char *nm)
        int i = masks.size();
        while( --i >= 0 ) {
                if( strcmp(masks[i]->name, nm) ) continue;
-               masks.remove_object_number(i);
+               masks.remove_object_number(i++);
        }
        mask = new SubMask(0, -1);
        strncpy(mask->name, nm, sizeof(mask->name)-1);
@@ -3100,7 +3100,7 @@ int CWindowMaskGUI::del_mask(const char *nm)
        int i = masks.size();
        while( --i >= 0 ) {
                if( strcmp(masks[i]->name, nm) ) continue;
-               masks.remove_object_number(i);
+               masks.remove_object_number(i++);
        }
        save_masks(masks);
        masks.remove_all_objects();
index 7d04cc8dc856e10adf34e7e4acade124af892f6b..dbda78c10612085bb960d17727ae60bf2fe7b4a3 100644 (file)
@@ -34,6 +34,7 @@
 #include "edits.h"
 #include "edl.h"
 #include "edlsession.h"
+#include "file.h"
 #include "filexml.h"
 #include "floatauto.h"
 #include "floatautos.h"
@@ -600,7 +601,7 @@ void EDL::copy_indexables(EDL *edl)
        }
 }
 
-EDL *EDL::new_nested(EDL *edl, const char *path)
+EDL *EDL::new_nested_edl(EDL *edl, const char *path)
 {
        EDL *nested = new EDL;  // no parent for nested edl
        nested->create_objects();
@@ -613,6 +614,22 @@ EDL *EDL::new_nested(EDL *edl, const char *path)
        return nested;
 }
 
+EDL *EDL::get_nested_edl()
+{
+       Track *track = tracks->first;
+       Edit *edit = track ? track->edits->first : 0;
+       EDL *nested = edit && !edit->next && !edit->asset ? edit->nested_edl : 0;
+       while( nested && (track=track->next)!=0 ) {
+               Edit *edit = track->edits->first;
+               if( !edit || edit->next ||
+                   ( edit->nested_edl != nested &&
+                     strcmp(edit->nested_edl->path, nested->path) ) )
+                       nested = 0;
+       }
+       return nested;
+}
+
+
 EDL *EDL::create_nested_clip(EDL *nested)
 {
        EDL *new_edl = new EDL(this);  // parent for clip edl
@@ -623,14 +640,46 @@ EDL *EDL::create_nested_clip(EDL *nested)
 
 void EDL::create_nested(EDL *nested)
 {
+       int video_tracks = 0, audio_tracks = 0;
+       for( Track *track=nested->tracks->first; track!=0; track=track->next ) {
+               if( track->data_type == TRACK_VIDEO && track->record ) ++video_tracks;
+               if( track->data_type == TRACK_AUDIO && track->record ) ++audio_tracks;
+       }
+// renderengine properties
+       if( video_tracks > 0 )
+               video_tracks = 1;
+       if( audio_tracks > 0 )
+               audio_tracks = nested->session->audio_channels;
+       
 // Keep frame rate, sample rate, and output size unchanged.
 // Nest all video & audio outputs
+       session->video_channels = video_tracks;
+       session->audio_channels = audio_tracks;
        session->video_tracks = 1;
-       session->audio_tracks = nested->session->audio_channels;
+       session->audio_tracks = audio_tracks;
        create_default_tracks();
        insert_asset(0, nested, 0, 0, 0);
 }
 
+void EDL::overwrite_clip(EDL *clip)
+{
+       int folder = folder_no;
+       char clip_title[BCTEXTLEN];  strcpy(clip_title, local_session->clip_title);
+       char clip_notes[BCTEXTLEN];  strcpy(clip_notes, local_session->clip_notes);
+       char clip_icon[BCSTRLEN];    strcpy(clip_icon,  local_session->clip_icon);
+       copy_all(clip);
+       folder_no = folder;
+       strcpy(local_session->clip_title, clip_title);
+       strcpy(local_session->clip_notes, clip_notes);
+       strcpy(local_session->clip_icon, clip_icon);
+       if( !clip_icon[0] ) return;
+// discard old clip icon to reconstruct 
+       char clip_icon_path[BCTEXTLEN];
+       snprintf(clip_icon_path, sizeof(clip_icon_path),
+               "%s/%s", File::get_config_path(), clip_icon);
+       remove(clip_icon_path);
+}
+
 void EDL::retrack()
 {
        int min_w = session->output_w, min_h = session->output_h;
@@ -1158,7 +1207,7 @@ void EDL::insert_asset(Asset *asset,
 
        if( new_nested_edl ) {
                length = new_nested_edl->tracks->total_length();
-               layers = 1;
+               layers = new_nested_edl->session->video_channels;
                channels = new_nested_edl->session->audio_channels;
        }
 
index 3e201a0748c03de775c3b6a502e944077762ee30..8656c6080c2f95e44c70a90ef5e329c8582f4a62 100644 (file)
@@ -196,9 +196,11 @@ public:
        int copy_assets(int copy_flags, double start, double end,
                FileXML *file, const char *output_path);
        void copy_indexables(EDL *edl);
-       EDL *new_nested(EDL *edl, const char *path);
+       EDL *new_nested_edl(EDL *edl, const char *path);
+       EDL *get_nested_edl();
        EDL *create_nested_clip(EDL *nested);
        void create_nested(EDL *nested);
+       void overwrite_clip(EDL *clip);
        void paste_silence(double start, double end,
                int edit_labels /* = 1 */,
                int edit_plugins,
index d932f67975b964e973649297ba46f0c0988f7ea3..8d27ff96c603cfad465ab33b760a9d4d78192bc9 100644 (file)
@@ -180,7 +180,6 @@ extern "C"
 
 }
 
-
 extern long cin_timezone;
 
 ArrayList<PluginServer*>* MWindow::plugindb = 0;
@@ -1312,7 +1311,7 @@ void MWindow::stop_mixers()
        }
 }
 
-void MWindow::close_mixers(int destroy)
+void MWindow::close_mixers(int result)
 {
        ArrayList<ZWindow*> closed;
        zwindows_lock->lock("MWindow::close_mixers");
@@ -1320,10 +1319,9 @@ void MWindow::close_mixers(int destroy)
                ZWindow *zwindow = zwindows[i];
                if( zwindow->idx < 0 ) continue;
                zwindow->idx = -1;
-               zwindow->destroy = destroy;
                ZWindowGUI *zgui = zwindow->zgui;
                zgui->lock_window("MWindow::select_zwindow 0");
-               zgui->set_done(0);
+               zgui->set_done(result);
                zgui->unlock_window();
                closed.append(zwindow);
        }
@@ -3734,6 +3732,122 @@ void MWindow::update_project(int load_mode)
        if(debug) PRINT_TRACE
 }
 
+void MWindow::stack_push(EDL *new_edl)
+{
+// needs gui lock
+       gui->lock_window("MWindow::stack_push");
+       if( stack.size() < 9 ) {
+               undo_before();
+               StackItem &item = stack.append();
+               item.edl = edl;
+               item.new_edl = new_edl;
+               item.undo = undo;
+               edl = new_edl;
+               edl->add_user();
+               strcpy(session->filename, edl->path);
+               undo = new MainUndo(this);
+               gui->stack_button->update();
+               update_project(LOADMODE_REPLACE);
+       }
+       gui->unlock_window();
+}
+
+void MWindow::stack_pop()
+{
+       if( !stack.size() ) return;
+// writes on config_path/backup%d.xml
+       save_backup();
+// already have gui lock
+       forget_nested_edl(edl);
+       StackItem &item = stack.last();
+// session edl replaced, overwrite and save clip data
+       if( item.new_edl != edl && item.new_edl->parent_edl )
+               item.new_edl->overwrite_clip(edl);
+       edl->remove_user();
+       edl = item.edl;
+       delete undo;
+       undo = item.undo;
+       stack.remove();
+       strcpy(session->filename, edl->path);
+       update_project(LOADMODE_REPLACE);
+       undo_after(_("open edl"), LOAD_ALL);
+       gui->stack_button->update();
+}
+
+void MWindow::forget_nested_edl(EDL *nested)
+{
+       frame_cache->remove_item(nested);
+       wave_cache->remove_item(nested);
+       if( gui->render_engine &&
+           gui->render_engine_id == nested->id ) {
+               delete gui->render_engine;
+               gui->render_engine = 0;
+       }
+       if( gui->resource_thread->render_engine_id == nested->id ) {
+               gui->resource_thread->render_engine_id = -1;
+               delete gui->resource_thread->render_engine;
+               gui->resource_thread->render_engine = 0;
+       }
+}
+
+void MWindow::clip_to_media()
+{
+       if( edl->session->proxy_scale != 1 ) {
+               eprintf("Nesting not allowed when proxy scale != 1");
+               return;
+       }
+       undo_before();
+       int clips_total = session->drag_clips->total;
+       for( int i=0; i<clips_total; ++i ) {
+               EDL *clip = session->drag_clips->values[i];
+               time_t dt;      time(&dt);
+               struct tm dtm;  localtime_r(&dt, &dtm);
+               char path[BCSTRLEN], *cp = path, *ep = cp+sizeof(path)-1;
+               cp += snprintf(cp, ep-cp, _("Nested_%02d%02d%02d-%02d%02d%02d_"),
+                       dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
+                       dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
+               cp += snprintf(cp, ep-cp, clip->local_session->clip_title);
+               EDL *nested = edl->new_nested_edl(clip, path);
+               edl->clips.remove(clip);
+               clip->remove_user();
+               mainindexes->add_next_asset(0, nested);
+       }
+       undo_after(_("clip2media"), LOAD_ALL);
+       mainindexes->start_build();
+       awindow->gui->async_update_assets();
+}
+
+void MWindow::media_to_clip()
+{
+       undo_before();
+       int assets_total = session->drag_assets->total;
+       for( int i=0; i<assets_total; ++i ) {
+               Indexable *idxbl = session->drag_assets->values[i];
+               if( idxbl->is_asset ) {
+                       eprintf(_("media is not EDL:\n%s"), idxbl->path);
+                       continue;
+               }
+               char clip_title[BCSTRLEN];
+               int name_ok = 0;
+               while( !name_ok ) {
+                       name_ok = 1;
+                       sprintf(clip_title, _("Clip %d"), session->clip_number++);
+                       for( int i=0; name_ok && i<edl->clips.size(); ++i ) {
+                               char *title = edl->clips[i]->local_session->clip_title;
+                               if( !strcasecmp(clip_title, title) ) name_ok = 0;
+                       }
+               }
+               EDL *nested = (EDL *)idxbl;
+               EDL *clip = edl->add_clip(nested);
+               strcpy(clip->local_session->clip_title, clip_title);
+               snprintf(clip->local_session->clip_notes,
+                       sizeof(clip->local_session->clip_notes),
+                       _("From: %s"), nested->path);
+       }
+       undo_after(_("media2clip"), LOAD_ALL);
+       awindow->gui->async_update_assets();
+}
+
 void MWindow::update_preferences(Preferences *prefs)
 {
        if( prefs != preferences )
@@ -3807,24 +3921,29 @@ void MWindow::rebuild_indices()
 }
 
 
+void MWindow::get_backup_path(char *path, int len)
+{
+       char *cp = path, *ep = cp + len-1;
+       cp += snprintf(cp, ep-cp, "%s/", File::get_config_path());
+       int idx = stack.size();
+       cp += snprintf(cp, ep-cp, idx ? BACKUPn_FILE : BACKUP_FILE, idx);
+}
+
 void MWindow::save_backup()
 {
        FileXML file;
        edl->optimize();
        edl->set_path(session->filename);
+
        char backup_path[BCTEXTLEN], backup_path1[BCTEXTLEN];
-       snprintf(backup_path, sizeof(backup_path), "%s/%s",
-               File::get_config_path(), BACKUP_FILE);
-       snprintf(backup_path1, sizeof(backup_path1), "%s/%s",
-               File::get_config_path(), BACKUP_FILE1);
+       get_backup_path(backup_path, sizeof(backup_path));
        rename(backup_path, backup_path1);
        edl->save_xml(&file, backup_path);
        file.terminate_string();
        FileSystem fs;
        fs.complete_path(backup_path);
 
-       if(file.write_to_file(backup_path))
-       {
+       if(file.write_to_file(backup_path)) {
                char string2[256];
                sprintf(string2, _("Couldn't open %s for writing."), backup_path);
                gui->show_message(string2);
@@ -3837,8 +3956,7 @@ void MWindow::load_backup()
        path_list.set_array_delete();
        char *out_path;
        char backup_path[BCTEXTLEN];
-       snprintf(backup_path, sizeof(backup_path), "%s/%s",
-               File::get_config_path(), BACKUP_FILE);
+       get_backup_path(backup_path, sizeof(backup_path));
        FileSystem fs;
        fs.complete_path(backup_path);
 
index 66b43626f63c52f9e0fb56720a89aaa7eb5a73ad..e938b743c8fb7beaa4566bc1e7c16ee1e9a4cdca 100644 (file)
 
 #define FONT_SEARCHPATH "fonts"
 
+class StackItem
+{
+public:
+       EDL *edl, *new_edl;
+       MainUndo *undo;
+};
+
+class Stack : public ArrayList<StackItem>
+{
+public:
+};
+
 
 class MWindow : public Thread
 {
@@ -135,6 +147,12 @@ public:
        int get_tracks_height();
 // Total horizontal pixels in timeline
        int get_tracks_width();
+// session stack
+       void stack_push(EDL *edl);
+       void stack_pop();
+       void forget_nested_edl(EDL *nested);
+       void clip_to_media();
+       void media_to_clip();
 // Show windows
        void show_vwindow();
        void show_awindow();
@@ -218,7 +236,7 @@ public:
        void create_mixers(double position = 0);
        void refresh_mixers(int dir=1);
        void stop_mixers();
-       void close_mixers(int destroy=1);
+       void close_mixers(int result=1);
        void open_mixers();
        ZWindow *get_mixer(Mixer *&mixer);
        void del_mixer(ZWindow *zwindow);
@@ -289,6 +307,7 @@ public:
        void split_y();
        void crop_video(int mode);
        void update_plugins();
+       void get_backup_path(char *path, int len);
 // Call after every edit operation
        void save_backup();
        void load_backup();
@@ -564,6 +583,8 @@ public:
 // Main undo stack
        MainUndo *undo;
        int undo_command;
+// session stack
+       Stack stack;
 
        BC_Hash *defaults;
        Assets *assets;
index 09c8043b97b9bea3a7e63a16f17f922aa00e505d..94d8c4b508988ef2a3e9a54b90ee6ed1c4344faf 100644 (file)
@@ -2177,28 +2177,24 @@ void MWindow::save_clip(EDL *new_edl, const char *txt)
         time_t now;  time(&now);
         struct tm dtm;   localtime_r(&now, &dtm);
        char *cp = new_edl->local_session->clip_notes;
-       int n, sz = sizeof(new_edl->local_session->clip_notes)-1;
-       if( txt && *txt ) {
-               n = snprintf(cp, sz, "%s", txt);
-               cp += n;  sz -= n;
-       }
-       n = snprintf(cp, sz,
+       char *ep = cp + sizeof(new_edl->local_session->clip_notes)-1;
+       if( txt && *txt )
+               cp += snprintf(cp, ep-cp, "%s", txt);
+       cp += snprintf(cp, ep-cp,
                "%02d/%02d/%02d %02d:%02d:%02d,  +%s\n",
                dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
                dtm.tm_hour, dtm.tm_min, dtm.tm_sec, duration);
-       cp += n;  sz -= n;
        if( path && *path ) {
                FileSystem fs;
                char title[BCTEXTLEN];
                fs.extract_name(title, path);
-               n = snprintf(cp, sz, "%s", title);
-               cp += n;  sz -= n;
+               cp += snprintf(cp, ep-cp, "%s", title);
        }
-       cp[n] = 0;
        sprintf(new_edl->local_session->clip_icon,
-               "clip_%02d%02d%02d-%02d%02d%02d.png",
+               "clip_%02d%02d%02d-%02d%02d%02d-%d.png",
                dtm.tm_year+1900, dtm.tm_mon+1, dtm.tm_mday,
-               dtm.tm_hour, dtm.tm_min, dtm.tm_sec);
+               dtm.tm_hour, dtm.tm_min, dtm.tm_sec,
+               new_edl->id);
        new_edl->folder_no = AW_CLIP_FOLDER;
        edl->update_assets(new_edl);
        int cur_x, cur_y;
index 248a56004a9d4b3f0297238583143a8b2ccbe845..e295c1508a6e1827518a3db5ef3dbf071285ceb2 100644 (file)
@@ -100,6 +100,7 @@ MWindowGUI::MWindowGUI(MWindow *mwindow)
        drag_popup = 0;
 
        render_engine = 0;
+       render_engine_id = -1;
        for(int i = 0; i < TOTAL_PANES; i++)
                pane[i] = 0;
 
@@ -168,20 +169,21 @@ void MWindowGUI::create_objects()
 
        if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
 
-       int x = get_w() - MainShBtns::calculate_w(-1, 0, -1);
-       add_subwindow(mainmenu = new MainMenu(mwindow, this, x));
-       mainmenu->create_objects();
-       add_subwindow(mainshbtns = new MainShBtns(mwindow, x, -1));
+       int x1 = get_w() - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
+       add_subwindow(mainshbtns = new MainShBtns(mwindow, x1, -1));
        mainshbtns->load(mwindow->preferences);
+       int x2 = x1 - mwindow->theme->stack_button_w - xS(5);
+       add_subwindow(stack_button = new StackButton(mwindow, x2, yS(2)));
+       add_subwindow(mainmenu = new MainMenu(mwindow, this, x2));
+       mainmenu->create_objects();
        mwindow->theme->get_mwindow_sizes(this, get_w(), get_h());
        mwindow->theme->draw_mwindow_bg(this);
        if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
 
        add_subwindow(mbuttons = new MButtons(mwindow, this));
        mbuttons->create_objects();
-       int x1 = mbuttons->get_x() + mbuttons->get_w(), y1 = mbuttons->get_y()+yS(2);
-       add_subwindow(proxy_toggle = new ProxyToggle(mwindow, mbuttons, x1, y1));
-       x1 += proxy_toggle->get_w() + xS(3);
+       int y1 = mbuttons->get_y()+yS(2);
+       add_subwindow(proxy_toggle = new ProxyToggle(mwindow, mbuttons, x2, y1));
        add_subwindow(ffmpeg_toggle = new FFMpegToggle(mwindow, mbuttons, x1, y1));
 
        pane[TOP_LEFT_PANE] = new TimelinePane(mwindow,
@@ -289,15 +291,16 @@ int MWindowGUI::resize_event(int w, int h)
 //printf("MWindowGUI::resize_event %d\n", __LINE__);
        mwindow->session->mwindow_w = w;
        mwindow->session->mwindow_h = h;
-       int x = w - MainShBtns::calculate_w(-1, 0, -1);
-       mainmenu->resize_event(x, mainmenu->get_h());
-       mainshbtns->reposition_window(x, -1);
+       int x1 = get_w() - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
+       mainshbtns->reposition_window(x1, -1);
+       int x2 = x1 - mwindow->theme->stack_button_w - xS(5);
+       stack_button->reposition_window(x2, stack_button->get_y());
+       mainmenu->resize_event(x2, mainmenu->get_h());
        mwindow->theme->get_mwindow_sizes(this, w, h);
        mwindow->theme->draw_mwindow_bg(this);
        mbuttons->resize_event();
-       int x1 = mbuttons->get_x() + mbuttons->get_w(), y1 = mbuttons->get_y()+yS(2);
-       proxy_toggle->reposition_window(x1, y1);
-       x1 += proxy_toggle->get_w() + xS(3);
+       int y1 = mbuttons->get_y()+yS(2);
+       proxy_toggle->reposition_window(x2, y1);
        ffmpeg_toggle->reposition_window(x1, y1);
        statusbar->resize_event();
        zoombar->resize_event();
@@ -609,6 +612,7 @@ void MWindowGUI::flash_canvas(int flush)
 int MWindowGUI::show_window(int flush)
 {
        int ret = BC_WindowBase::show_window(flush);
+       stack_button->update();
        update_proxy_toggle();
        return ret;
 }
@@ -2298,6 +2302,34 @@ int FFMpegToggle::handle_event()
 }
 
 
+StackButton::StackButton(MWindow *mwindow, int x, int y)
+ : BC_GenericButton(x, y, mwindow->theme->stack_button_w, "0")
+{
+       this->mwindow = mwindow;
+       set_tooltip(_("Return to previous EDL"));
+}
+
+int StackButton::handle_event()
+{
+       mwindow->stack_pop();
+       return 1;
+}
+
+void StackButton::update()
+{
+       char text[BCSTRLEN];
+       int i = mwindow->stack.size();
+       sprintf(text, "%d", i);
+       set_text(text);
+       draw_face();
+       int hidden = is_hidden();
+       if( !i && !hidden )
+               hide_window();
+       else if( hidden )
+               show_window();
+}
+
+
 ProxyToggle::ProxyToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
  : BC_Toggle(x, y, ( !mwindow->edl->session->proxy_use_scaler ?
                        mwindow->theme->proxy_p_toggle :
index 68e0a4f7707fcab015a1029b6b04a5db459a77a4..4ba7c16ebe164cad80855f04d9ba90d37a791fde 100644 (file)
@@ -79,6 +79,16 @@ public:
        MButtons *mbuttons;
 };
 
+class StackButton : public BC_GenericButton
+{
+public:
+       StackButton(MWindow *mwindow, int x, int y);
+       int handle_event();
+       void update();
+
+       MWindow *mwindow;
+};
+
 class ProxyToggle : public BC_Toggle
 {
 public:
@@ -225,6 +235,7 @@ public:
        MButtons *mbuttons;
        FFMpegToggle *ffmpeg_toggle;
        ProxyToggle *proxy_toggle;
+       StackButton *stack_button;
        PaneDivider *x_divider;
        PaneDivider *y_divider;
        TimelinePane *pane[TOTAL_PANES];
index 00686a4512293248f3dac1f98c80e52b86787f9a..0d6e53302be21286c58bc59d233de38e57165ac1 100644 (file)
@@ -25,6 +25,7 @@
 // Run-time configuration directory
 #define DEAMON_PORT 400
 #define BACKUP_FILE "backup.xml"
+#define BACKUPn_FILE "backup%d.xml"
 #define BACKUP_FILE1 "backup.prev"
 #define LAYOUT_FILE "layout%d_rc"
 #define LAYOUT_NAME_LEN 8
index ae861e96f21d863fc417bd7f51222b04fc83fb3e..076b0436cf1dbd85c8daa9379db37a487db4c046 100644 (file)
@@ -174,6 +174,7 @@ ResourceThread::ResourceThread(MWindow *mwindow, MWindowGUI *gui)
        prev_l = 0;
        operation_count = 0;
        render_engine = 0;
+       render_engine_id = -1;
 
        audio_asset = 0;
        audio_source = 0;
index d35e475096b88eda2685b7b0aa718370b3f6b381..efb513f052a58ec582a1d65878e9ca25f06f618a 100644 (file)
@@ -70,6 +70,7 @@ Theme::Theme()
        mtransport_margin = 0;
        toggle_margin = 0;
        control_pixels = xS(50);
+       stack_button_w = xS(32);
        timebar_cursor_color = RED;
 
        BC_WindowBase::get_resources()->bg_color = BLOND;
@@ -608,7 +609,9 @@ void Theme::get_mwindow_sizes(MWindowGUI *gui, int w, int h)
 {
        mbuttons_x = 0;
        mbuttons_y = gui->menu_h() + yS(1);
-       mbuttons_w = w - (ffmpeg_toggle[0]->get_w()+2 + proxy_p_toggle[0]->get_w()+xS(2));
+       mbuttons_w = w - (ffmpeg_toggle[0]->get_w()+xS(2) +
+                        proxy_p_toggle[0]->get_w()+xS(2) +
+                        stack_button_w);
        mbuttons_h = get_image("mbutton_bg")->get_h();
        mclock_x = window_border - xS(5);
        mclock_y = mbuttons_y-1 + mbuttons_h;
index 1b1e4b38111812fffe90d11b2f350e189b217376..f0eb5cf2299bc3ca28729d3c5b34c5609c457545 100644 (file)
@@ -165,6 +165,7 @@ public:
        int adivider_x, adivider_y, adivider_w, adivider_h;
        int afolders_x, afolders_y, afolders_w, afolders_h;
        int alist_x, alist_y, alist_w, alist_h;
+       int stack_button_w;
        int audio_color;
 // audio zero crossing
        int zero_crossing_color;
index 7f6d2800b8f0279c175bacaea9c5a0ea1ecae706..f40e804b19d3f73e412366e4ad1883d24e04ea80 100644 (file)
@@ -185,7 +185,6 @@ ZWindow::ZWindow(MWindow *mwindow)
        idx = -1;
        edl = 0;
        highlighted = 0;
-       destroy = 1;
        title[0] = 0;
        zgui = 0;
 }
@@ -207,10 +206,10 @@ BC_Window* ZWindow::new_gui()
 
 void ZWindow::handle_done_event(int result)
 {
-       idx = -1;
        stop_playback(1);
-       if( destroy )
+       if( result )
                mwindow->del_mixer(this);
+       idx = -1;
 }
 void ZWindow::handle_close_event(int result)
 {
index fcd05699c1f7c45084474a75f378844f6860a00f..1c6f4ce077b65be5a4720ba96ab78288986028ba 100644 (file)
@@ -81,7 +81,7 @@ public:
        ZWindowGUI *zgui;
        EDL* edl;
 
-       int idx, destroy;
+       int idx;
        int highlighted;
        char title[BCTEXTLEN];
 };
index b6cccd03f82352ce4f285a98ccc267bf754f644e..90cd349a536fe5c8a78e5aa920e5c7a1516ed46a 100644 (file)
@@ -85,7 +85,7 @@ int ZWindowGUI::translation_event()
 
 int ZWindowGUI::close_event()
 {
-       set_done(0);
+       set_done(1);
        return 1;
 }
 
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s16le.mka b/cinelerra-5.1/ffmpeg/audio/user_s16le.mka
new file mode 100644 (file)
index 0000000..5712422
--- /dev/null
@@ -0,0 +1,6 @@
+matroska pcm_s16le
+# PCM signed 16-bit little-endian (pcm_s16le) in
+# Matroska (Audio) container.
+# The extension should be "mka".
+# ffmpeg --help encoder=pcm_s16le
+# ffmpeg --help muxer=matroska
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s16le.mkv b/cinelerra-5.1/ffmpeg/audio/user_s16le.mkv
new file mode 100644 (file)
index 0000000..47a3a11
--- /dev/null
@@ -0,0 +1,7 @@
+matroska pcm_s16le
+# PCM signed 16-bit little-endian (pcm_s16le) in
+# Matroska container.
+# If only audio is exported, the extension should
+# be "mka".
+# ffmpeg --help encoder=pcm_s16le
+# ffmpeg --help muxer=matroska
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s16le.w64 b/cinelerra-5.1/ffmpeg/audio/user_s16le.w64
new file mode 100644 (file)
index 0000000..84d6718
--- /dev/null
@@ -0,0 +1,6 @@
+w64 pcm_s16le
+# Pure audio format.
+# PCM signed 16-bit little-endian (pcm_s16le) in
+# Sony Pictures Digital Wave 64 (Wave64, .w64)
+# ffmpeg --help encoder=pcm_s16le
+# ffmpeg --help muxer=w64
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s24le-2.mkv b/cinelerra-5.1/ffmpeg/audio/user_s24le-2.mkv
new file mode 100644 (file)
index 0000000..7eddfe5
--- /dev/null
@@ -0,0 +1,7 @@
+matroska pcm_s24le
+# PCM signed 24-bit little-endian (pcm_s24le) in
+# Matroska container.
+# If only audio is exported, the extension should
+# be "mka".
+# ffmpeg --help encoder=pcm_s24le
+# ffmpeg --help muxer=matroska
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s24le.mka b/cinelerra-5.1/ffmpeg/audio/user_s24le.mka
new file mode 100644 (file)
index 0000000..4db4d3b
--- /dev/null
@@ -0,0 +1,6 @@
+matroska pcm_s24le
+# PCM signed 24-bit little-endian (pcm_s24le) in
+# Matroska (Audio) container.
+# The extension should be "mka".
+# ffmpeg --help encoder=pcm_s24le
+# ffmpeg --help muxer=matroska
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s24le.w64 b/cinelerra-5.1/ffmpeg/audio/user_s24le.w64
new file mode 100644 (file)
index 0000000..4d92a43
--- /dev/null
@@ -0,0 +1,6 @@
+w64 pcm_s24le
+# Pure audio format.
+# PCM signed 24-bit little-endian (pcm_s24le) in
+# Sony Pictures Digital Wave 64 (Wave64, .w64)
+# ffmpeg --help encoder=pcm_s24le
+# ffmpeg --help muxer=w64
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s32le.mka b/cinelerra-5.1/ffmpeg/audio/user_s32le.mka
new file mode 100644 (file)
index 0000000..b742251
--- /dev/null
@@ -0,0 +1,6 @@
+matroska pcm_s32le
+# PCM signed 32-bit little-endian (pcm_s32le) in
+# Matroska (Audio) container.
+# The extension should be "mka".
+# ffmpeg --help encoder=pcm_s32le
+# ffmpeg --help muxer=matroska
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s32le.mkv b/cinelerra-5.1/ffmpeg/audio/user_s32le.mkv
new file mode 100644 (file)
index 0000000..6d092e4
--- /dev/null
@@ -0,0 +1,7 @@
+matroska pcm_s32le
+# PCM signed 32-bit little-endian (pcm_s32le) in
+# Matroska container.
+# If only audio is exported, the extension should
+# be "mka".
+# ffmpeg --help encoder=pcm_s32le
+# ffmpeg --help muxer=matroska
diff --git a/cinelerra-5.1/ffmpeg/audio/user_s32le.w64 b/cinelerra-5.1/ffmpeg/audio/user_s32le.w64
new file mode 100644 (file)
index 0000000..48e5b94
--- /dev/null
@@ -0,0 +1,6 @@
+w64 pcm_s32le
+# Pure audio format.
+# PCM signed 32-bit little-endian (pcm_s32le) in
+# Sony Pictures Digital Wave 64 (Wave64, .w64)
+# ffmpeg --help encoder=pcm_s32le
+# ffmpeg --help muxer=w64
index e4088e55971c841d5286ffb9a124a7913d3ecac5..03256e60f3b7a68bd8d633e43b07d1b377d14767 100644 (file)
@@ -480,7 +480,11 @@ int BC_GenericButton::draw_face(int flush)
        return 0;
 }
 
-
+void BC_GenericButton::set_text(const char *cp)
+{
+       strncpy(text, cp, sizeof(text));
+       draw_face();
+}
 
 
 
index 2250dc6dc3f3993714607c08701b9d95fb314477..372b4d30a7abf0e103cbc09dda5237d5d23f1c24 100644 (file)
@@ -75,6 +75,8 @@ private:
 
 class BC_GenericButton : public BC_Button
 {
+       int color;
+       char text[BCTEXTLEN];
 public:
        BC_GenericButton(int x, int y,
                const char *text, VFrame **data = 0, int color=-1);
@@ -85,10 +87,8 @@ public:
        int draw_face(int flash = 1);
        static int calculate_w(BC_WindowBase *gui, const char *text);
        static int calculate_h();
+       void set_text(const char *cp);
        const char *get_text () { return text; }
-private:
-       int color;
-       char text[BCTEXTLEN];
 };
 
 class BC_OKTextButton : public BC_GenericButton
index f94ee16512ee7652c3339114b89cfbe2c2735f21..a362095e3405c0084f0e170460465d1248076152 100644 (file)
@@ -2437,6 +2437,8 @@ void BC_WindowBase::init_glyphs()
 //  Not a fix, but much better than nothing.
        static int inited = 0;
        if( inited ) return;
+       XGrabServer(display);
+       XSync(display, 0);
        inited = 1;
        int cur_font = current_font;
 // locale encodings, needed glyphs to be preloaded
@@ -2449,6 +2451,7 @@ void BC_WindowBase::init_glyphs()
                draw_text(5,5, text, 0);
        }
        set_font(cur_font);
+       XUngrabServer(display);
 }
 
 void BC_WindowBase::init_im()
index d8f30152debe37ee5741945499e80fcf8f8db955..c94be14fc09a0f9727a72d272794ae28a9f1bbe9 100644 (file)
 #include "bcsignals.h"
 #include "guicast.h"
 
-
-
+/*
+c++ x.C -I/mnt1/build5/cinelerra-5.1/guicast \
+  -L/mnt1/build5/cinelerra-5.1/guicast/x86_64 -lguicast \
+  -DHAVE_GL -DHAVE_XFT -I/usr/include/freetype2 -lGL -lX11 -lXext \
+  -lXinerama -lXv -lpng  -lfontconfig -lfreetype -lXft -pthread
+*/
 
 class TestWindow : public BC_Window
 {
@@ -32,18 +36,21 @@ public:
 
        void create_objects()
        {
+               lock_window("TestWindow::create_objects");
                set_color(BLACK);
                set_font(LARGEFONT);
                draw_text(10, 50, "Hello world");
                flash();
                flush();
+               unlock_window();
        };
 };
 
 
 int main()
 {
-       new BC_Signals;
+       BC_Signals signals;
+       BC_WindowBase::init_resources(1.);
        TestWindow window;
        window.create_objects();
        window.run_window();
index 293205821fc9090da5f1a4b136539cc26497c174..869bba0e9be05e0e7cd93d9baa2f6d3efd56a2a3 100644 (file)
@@ -276,6 +276,8 @@ int VFrame::reset_parameters(int do_opengl)
        is_keyframe = 0;
        pixel_rgb = 0x000000; // BLACK
        pixel_yuv = 0x008080;
+       draw_alpha = 1.f;
+       draw_flags = ALIAS_OFF;
        stipple = 0;
        clear_color = 0x000000;
        clear_alpha = 0x00;
@@ -1394,109 +1396,120 @@ int VFrame::get_memory_usage()
 // a (~alpha) transparency, 0x00==solid .. 0xff==transparent
 void VFrame::set_pixel_color(int rgb, int a)
 {
-       pixel_rgb = (rgb&0xffffff) | ~a<<24;
+       pixel_rgb = (~a<<24) | (rgb&0xffffff);
        int ir = 0xff & (pixel_rgb >> 16);
        int ig = 0xff & (pixel_rgb >> 8);
        int ib = 0xff & (pixel_rgb >> 0);
        YUV::yuv.rgb_to_yuv_8(ir, ig, ib);
-       pixel_yuv =  (~a<<24) | (ir<<16) | (ig<<8) | (ib<<0);
+       pixel_yuv = (~a<<24) | (ir<<16) | (ig<<8) | (ib<<0);
 }
 
 void VFrame::set_stiple(int mask)
 {
        stipple = mask;
 }
-
-int VFrame::draw_pixel(int x, int y)
+void VFrame::set_draw_alpha(float alpha)
 {
-       if( x < 0 || y < 0 || x >= get_w() || y >= get_h() ) return 1;
-
-#define DRAW_PIXEL(type, r, g, b, comps, a) { \
-       type **rows = (type**)get_rows(); \
-       type *rp = rows[y], *bp = rp + x*comps; \
-       bp[0] = r; \
-       if( comps > 1 ) { bp[1] = g; bp[2] = b; } \
-       if( comps == 4 )  bp[3] = a; \
+       draw_alpha = alpha;
+}
+void VFrame::set_draw_flags(int flags)
+{
+       draw_flags = flags;
 }
+
+int VFrame::draw_pixel(float x, float y, float a)
+{
+       int ix = x, iy = y;
+       if( ix < 0 || iy < 0 || ix >= get_w() || iy >= get_h() ) return 1;
+       if( a <= 0 ) return 0;
+       if( a > 1 ) a = 1;
+       int color = BC_CModels::is_yuv(color_model) ? pixel_yuv : pixel_rgb;
        float fr = 0, fg = 0, fb = 0, fa = 0;
-       int pixel_color = BC_CModels::is_yuv(color_model) ? pixel_yuv : pixel_rgb;
-       int ir = (0xff & (pixel_color >> 16));
-       int ig = (0xff & (pixel_color >> 8));
-       int ib = (0xff & (pixel_color >> 0));
-       int ia = (0xff & (pixel_color >> 24)) ^ 0xff;  // transparency, not opacity
-       if( (x+y) & stipple ) {
+       int ir = (0xff & (color >> 16));
+       int ig = (0xff & (color >> 8));
+       int ib = (0xff & (color >> 0));
+       int ia = (0xff & ~(color >> 24));  // transparency, not opacity
+       if( (ix+iy) & stipple ) {
                ir = 255 - ir;  ig = 255 - ig;  ib = 255 - ib;
        }
        int rr = (ir<<8) | ir, gg = (ig<<8) | ig, bb = (ib<<8) | ib, aa = (ia<<8) | ia;
+       float fmax = 65535.f;  fa = aa/fmax;
        if( BC_CModels::is_float(color_model) ) {
-               fr = rr/65535.f;  fg = gg/65535.f;  fb = bb/65535.f;  fa = aa/65535.f;
+               fr = rr/fmax;  fg = gg/fmax;  fb = bb/fmax;
        }
 
+#define DRAW_PIXEL(cmdl, type, r, g, b, ofs, max, comps) \
+case cmdl: { \
+ float src_a = fa*draw_alpha, src_1a = 1 - src_a; \
+ type **rows = (type**)get_rows(); \
+ type *rp = rows[iy], *bp = rp + ix*comps; \
+ bp[0] = src_a * r + src_1a * bp[0]; \
+ if( comps > 1 ) { \
+  bp[1] = src_a * (g-ofs) + src_1a * (bp[1]-ofs) + ofs; \
+  bp[2] = src_a * (b-ofs) + src_1a * (bp[2]-ofs) + ofs; \
+ } \
+ if( comps == 4 ) \
+  bp[3] = src_a * max + src_1a * bp[3]; \
+ break;\
+}
+
        switch(get_color_model()) {
-       case BC_A8:
-               DRAW_PIXEL(uint8_t, ib, 0, 0, 1, 0);
-               break;
-       case BC_RGB888:
-       case BC_YUV888:
-               DRAW_PIXEL(uint8_t, ir, ig, ib, 3, 0);
-               break;
-       case BC_RGBA8888:
-       case BC_YUVA8888:
-               DRAW_PIXEL(uint8_t, ir, ig, ib, 4, ia);
-               break;
-       case BC_RGB161616:
-       case BC_YUV161616:
-               DRAW_PIXEL(uint16_t, rr, gg, bb, 3, 0);
-               break;
-       case BC_RGBA16161616:
-       case BC_YUVA16161616:
-               DRAW_PIXEL(uint16_t, rr, gg, bb, 4, aa);
-               break;
-       case BC_RGB_FLOAT:
-               DRAW_PIXEL(float, fr, fg, fb, 3, 0);
-               break;
-       case BC_RGBA_FLOAT:
-               DRAW_PIXEL(float, fr, fg, fb, 4, fa);
-               break;
+       DRAW_PIXEL(BC_A8,           uint8_t, ib,  0,  0, 0x00, 0xff, 1);
+       DRAW_PIXEL(BC_RGB888,       uint8_t, ir, ig, ib, 0x00, 0xff, 3);
+       DRAW_PIXEL(BC_YUV888,       uint8_t, ir, ig, ib, 0x80, 0xff, 3);
+       DRAW_PIXEL(BC_RGBA8888,     uint8_t, ir, ig, ib, 0x00, 0xff, 4);
+       DRAW_PIXEL(BC_YUVA8888,     uint8_t, ir, ig, ib, 0x80, 0xff, 4);
+       DRAW_PIXEL(BC_RGB161616,    uint16_t, rr, gg, bb, 0x0000, 0xffff, 3);
+       DRAW_PIXEL(BC_YUV161616,    uint16_t, rr, gg, bb, 0x8000, 0xffff, 3);
+       DRAW_PIXEL(BC_RGBA16161616, uint16_t, rr, gg, bb, 0x0000, 0xffff, 4);
+       DRAW_PIXEL(BC_YUVA16161616, uint16_t, rr, gg, bb, 0x8000, 0xffff, 4);
+       DRAW_PIXEL(BC_RGB_FLOAT,    float, fr, fg, fb, 0., 1., 3);
+       DRAW_PIXEL(BC_RGBA_FLOAT,   float, fr, fg, fb, 0., 1., 4);
        }
        return 0;
 }
 
+int VFrame::draw_pixel(float x, float y, float frac, int axis)
+{
+       if( draw_flags ) {
+               int xs = axis, ys = 1-axis;
+               if( draw_flags & ALIAS_TOP ) draw_pixel(x-xs, y-ys, 1-frac);
+               draw_pixel(x, y, draw_flags & ALIAS_CTR ? 1-frac : 1);
+               if( draw_flags & ALIAS_BOT ) draw_pixel(x+xs, y+ys, frac);
+       }
+       else
+               draw_pixel(x, y);
+       return 0;
+}
 
-// Bresenham's
-void VFrame::draw_line(int x1, int y1, int x2, int y2)
+void VFrame::draw_line(float x1, float y1, float x2, float y2)
 {
        if( y1 > y2 ) {
                int tx = x1;  x1 = x2;  x2 = tx;
                int ty = y1;  y1 = y2;  y2 = ty;
        }
-
-       int x = x1, y = y1;
-       int dx = x2-x1, dy = y2-y1;
-       int dx2 = 2*dx, dy2 = 2*dy;
-       if( dx < 0 ) dx = -dx;
-       int r = dx > dy ? dx : dy, n = r;
-       int dir = 0;
-       if( dx2 < 0 ) dir += 1;
-       if( dy >= dx ) {
-               if( dx2 >= 0 ) do {     /* +Y, +X */
-                       draw_pixel(x, y++);
-                       if( (r -= dx2) < 0 ) { r += dy2;  ++x; }
-               } while( --n >= 0 );
-               else do {               /* +Y, -X */
-                       draw_pixel(x, y++);
-                       if( (r += dx2) < 0 ) { r += dy2;  --x; }
-               } while( --n >= 0 );
+       float dx = x2-x1, dy = y2-y1;
+       float s = dx ? dy/dx : 1;
+       float t = dy ? dx/dy : 0;
+       int xs = dx < 0 ? -1 : 1;
+       dx *= xs;
+       int idx = (int)x2 - (int)x1;
+       int idy = (int)y2 - (int)y1;
+       int d = dx >= dy ? abs(idx) : idy;
+       float x = x1, y = y1;
+       if( dx > dy ) {
+               draw_pixel(x, y, y-(int)y, 0);
+               while( --d >= 0 ) {
+                       y = y1 + ((x += xs) - x1) * s;
+                       draw_pixel(x, y, y-(int)y, 0);
+               }
        }
        else {
-               if( dx2 >= 0 ) do {     /* +X, +Y */
-                       draw_pixel(x++, y);
-                       if( (r -= dy2) < 0 ) { r += dx2;  ++y; }
-               } while( --n >= 0 );
-               else do {               /* -X, +Y */
-                       draw_pixel(x--, y);
-                       if( (r -= dy2) < 0 ) { r -= dx2;  ++y; }
-               } while( --n >= 0 );
+               draw_pixel(x, y, x-(int)x, 1);
+               while( --d >= 0 ) {
+                       x = x1 + (++y - y1) * t;
+                       draw_pixel(x, y, x-(int)x, 1);
+               }
        }
 }
 
@@ -1562,7 +1575,15 @@ void smooth_line::draw()
                if( abs(rr) < abs(r) )
                        moveX(rr);
        }
-xit:   vframe->draw_pixel(sx, sy);
+xit:
+//     vframe->draw_pixel(sx, sy);
+       float vx = abs(dx), vy = abs(dy);
+       float vv = 4*(vx > vy ? dx : dy);
+       float frac = vv ? -r / vv : 0;
+       frac = (1+frac) / 2;
+       bclamp(frac, 0, 1);
+       int axis = abs(dx) >= abs(dy) ? 1 : 0;
+       vframe->draw_pixel(sx, sy, frac, axis);
 }
 
 void VFrame::draw_smooth(int x1, int y1, int x2, int y2, int x3, int y3)
@@ -1696,10 +1717,10 @@ void smooth_line::init1(int x1,int y1, int x2,int y2, int x3,int y3)
                xmxx = ex; xmxy = ey;
        }
        if( xs > 0 )
-               vframe->draw_pixel(sx, sy);
+               vframe->draw_pixel(sx, sy, 0, 0);
        while( xs*(sx-xmxx) < 0 && (xs*dx < 0 || rx() < 0) ) {
                moveX(rx());
-               vframe->draw_pixel(sx, sy);
+               vframe->draw_pixel(sx, sy, 0, 0);
        }
 }
 
@@ -1723,9 +1744,9 @@ void VFrame::smooth_draw(int x1, int y1, int x2, int y2, int x3, int y3)
        else if( y1 < y2 && y3 < y2 ) {
                smooth_line lt(this), rt(this); // Q on top
                lt.init0(x1, y1, x2, y2, x3, y3, 1);
-               draw_pixel(lt.sx, lt.sy);
+               draw_pixel(lt.sx, lt.sy, 0, 0);
                rt.init0(x1, y1, x2, y2, x3, y3, -1);
-               draw_pixel(rt.sx, rt.sy);
+               draw_pixel(rt.sx, rt.sy, 0, 0);
                while( !lt.done || !rt.done ) {
                        lt.draw();
                        rt.draw();
@@ -1734,7 +1755,7 @@ void VFrame::smooth_draw(int x1, int y1, int x2, int y2, int x3, int y3)
        else {
                smooth_line pt(this);           // Q in between
                pt.init0(x1, y1, x2, y2, x3, y3, 0);
-               draw_pixel(pt.sx, pt.sy);
+               draw_pixel(pt.sx, pt.sy, 0, 1);
                while( !pt.done ) {
                        pt.draw();
                }
index 5c717200ab16bb7b2099133b40eb174a7716c974..21b6497af9f6043691eaffa26e28462548444e2b 100644 (file)
 #define MAX_STACK_ELEMENTS 255
 #define SHM_MIN_SIZE 2048
 
+#define ALIAS_OFF 0
+#define ALIAS_TOP 1
+#define ALIAS_CTR 2
+#define ALIAS_BOT 4
+#define ALIAS_DBL 5
+#define ALIAS_NRM 6
+
 // Scene graph for 3D models
 // Defined by the subclass
 class VFrameScene
@@ -342,16 +349,20 @@ public:
        void copy_stacks(VFrame *src);
 // Updates the params with values from src
        void copy_params(VFrame *src);
-
 // This clears the stacks and the param table
        void clear_stacks();
 
-       virtual int draw_pixel(int x, int y);
-       int pixel_rgb, pixel_yuv, stipple;
+// pixel drawing
+       virtual int draw_pixel(float x, float y, float a=1.f);
+       virtual int draw_pixel(float x, float y, float frac, int axis);
+       void set_draw_alpha(float a);
+       void set_draw_flags(int flags);
+       int pixel_rgb, pixel_yuv, stipple, draw_flags;
+       float draw_alpha;
 
        void set_pixel_color(int rgb, int a=0xff);
        void set_stiple(int mask);
-       void draw_line(int x1, int y1, int x2, int y2);
+       void draw_line(float x1, float y1, float x2, float y2);
        void draw_smooth(int x1, int y1, int x2, int y2, int x3, int y3);
        void smooth_draw(int x1, int y1, int x2, int y2, int x3, int y3);
        void draw_rect(int x1, int y1, int x2, int y2);
index 8036cb8b40367fd3a98b8469f5e2539887e7801c..bd57f639fd6e909de47d8fa9d1dfa59198a367b7 100644 (file)
@@ -72,6 +72,12 @@ public:
        void create_objects();
        void update();
 
+       int close_event() { return colors->close_gui(); }
+       int cursor_motion_event() { return colors->cursor_motion_gui(); }
+       int button_press_event() { return colors->button_press_gui(); }
+       int button_release_event() { return colors->button_release_gui(); }
+       void done_event(int result) { colors->close_gui(); }
+
        ForegroundMain *plugin;
        ForegroundColors *colors;
 };
index 272bcf0458ec7f4618dac0eaf11080a2786f635e..2b392327176b85cdb35e3a22cd8283dd6ff85d3c 100644 (file)
@@ -242,6 +242,7 @@ REGISTER_PLUGIN(Sketcher)
 SketcherConfig::SketcherConfig()
 {
        drag = 1;
+       aliasing = 0;
        cv_selected = 0;
        pt_selected = 0;
 }
@@ -252,6 +253,7 @@ SketcherConfig::~SketcherConfig()
 int SketcherConfig::equivalent(SketcherConfig &that)
 {
        if( this->drag != that.drag ) return 0;
+       if( this->aliasing != that.aliasing ) return 0;
        if( this->cv_selected != that.cv_selected ) return 0;
        if( this->pt_selected != that.pt_selected ) return 0;
        if( this->curves.size() != that.curves.size() ) return 0;
@@ -264,6 +266,7 @@ int SketcherConfig::equivalent(SketcherConfig &that)
 void SketcherConfig::copy_from(SketcherConfig &that)
 {
        this->drag = that.drag;
+       this->aliasing = that.aliasing;
        this->cv_selected = that.cv_selected;
        this->pt_selected = that.pt_selected;
        int m = curves.size(), n = that.curves.size();
@@ -278,6 +281,7 @@ void SketcherConfig::interpolate(SketcherConfig &prev, SketcherConfig &next,
        this->cv_selected = prev.cv_selected;
        this->pt_selected = prev.pt_selected;
        this->drag = prev.drag;
+       this->aliasing = prev.aliasing;
 
        double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
        double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
@@ -360,6 +364,7 @@ void Sketcher::save_data(KeyFrame *keyframe)
 
        output.tag.set_title("SKETCHER");
        output.tag.set_property("DRAG", config.drag);
+       output.tag.set_property("ALIASING", config.aliasing);
        output.tag.set_property("CV_SELECTED", config.cv_selected);
        output.tag.set_property("PT_SELECTED", config.pt_selected);
        output.append_tag();
@@ -384,6 +389,7 @@ void Sketcher::read_data(KeyFrame *keyframe)
        while( !(result=input.read_tag()) ) {
                if( input.tag.title_is("SKETCHER") ) {
                        config.drag = input.tag.get_property("DRAG", config.drag);
+                       config.aliasing = input.tag.get_property("ALIASING", config.aliasing);
                        config.cv_selected = input.tag.get_property("CV_SELECTED", 0);
                        config.pt_selected = input.tag.get_property("PT_SELECTED", 0);
                }
@@ -438,47 +444,58 @@ void Sketcher::draw_point(VFrame *vfrm, SketcherPoint *pt, int color)
 }
 
 
-int SketcherVPen::draw_pixel(int x, int y)
+int SketcherVPen::draw_mask(int x, int y)
 {
-       if( x >= 0 && x < vfrm->get_w() &&
-           y >= 0 && y < vfrm->get_h() )
-               msk[vfrm->get_w()*y + x] = 0xff;
+       int w = vfrm->get_w(), h = vfrm->get_h();
+       if( x < 0 || x >= w ) return 1;
+       if( y < 0 || y >= h ) return 1;
+       msk[w * y + x] = 0xff;
        return 0;
 }
 
-int SketcherPenSquare::draw_pixel(int x, int y)
+int SketcherVPen::draw_pixel(float x, float y, float frac, int axis)
 {
+       draw_mask(x, y);
+       return VFrame::draw_pixel(x, y, frac, axis);
+}
+
+int SketcherPenSquare::draw_pixel(float x, float y, float a)
+{
+       vfrm->set_draw_alpha(a);
        vfrm->draw_line(x-n, y, x+n, y);
        for( int i=-n; i<n; ++i )
                vfrm->draw_line(x-n, y+i, x+n, y+i);
-       return SketcherVPen::draw_pixel(x, y);
+       return 0;
 }
-int SketcherPenPlus::draw_pixel(int x, int y)
+int SketcherPenPlus::draw_pixel(float x, float y, float a)
 {
+       vfrm->set_draw_alpha(a);
        if( n > 1 ) {
                vfrm->draw_line(x-n, y, x+n, y);
                vfrm->draw_line(x, y-n, x, y+n);
        }
        else
                vfrm->draw_pixel(x, y);
-       return SketcherVPen::draw_pixel(x, y);
+       return 0;
 }
-int SketcherPenSlant::draw_pixel(int x, int y)
+int SketcherPenSlant::draw_pixel(float x, float y, float a)
 {
+       vfrm->set_draw_alpha(a);
        vfrm->draw_line(x-n,   y+n,   x+n,   y-n);
        vfrm->draw_line(x-n+1, y+n,   x+n+1, y-n);
        vfrm->draw_line(x-n,   y+n+1, x+n,   y-n+1);
-       return SketcherVPen::draw_pixel(x, y);
+       return 0;
 }
-int SketcherPenXlant::draw_pixel(int x, int y)
+int SketcherPenXlant::draw_pixel(float x, float y, float a)
 {
+       vfrm->set_draw_alpha(a);
        vfrm->draw_line(x-n,   y+n,   x+n,   y-n);
        vfrm->draw_line(x-n+1, y+n,   x+n+1, y-n);
        vfrm->draw_line(x-n,   y+n+1, x+n,   y-n+1);
        vfrm->draw_line(x-n,   y-n,   x+n,   y+n);
        vfrm->draw_line(x-n+1, y-n,   x+n+1, y+n);
        vfrm->draw_line(x-n,   y-n+1, x+n,   y-n+1);
-       return SketcherVPen::draw_pixel(x, y);
+       return 0;
 }
 
 
@@ -563,6 +580,7 @@ class FillRegion
 public:
        SketcherPoint *next();
        bool exists() { return stack.size() > 0; }
+       void draw_pixel(int x, int y) { img->draw_pixel(x, y); }
        void start_at(int x, int y);
        void run();
        FillRegion(SketcherPoints &pts, SketcherVPen *vpen);
@@ -591,25 +609,26 @@ void FillRegion::start_at(int x, int y)
 
 void FillRegion::run()
 {
+       img->set_draw_alpha(1);
        while( stack.size() > 0 ) {
                int y, ilt, irt;
                pop(y, ilt, irt);
                int ofs = y*w + ilt;
                for( int x=ilt; x<=irt; ++x,++ofs ) {
+                       draw_pixel(x, y);
                        if( msk[ofs] ) continue;
                        msk[ofs] = 0xff;
-                       img->draw_pixel(x, y);
                        int lt = x, rt = x;
                        int lofs = ofs;
                        for( int i=lt; --i>=0; ) {
+                               draw_pixel(i, y);
                                if( msk[--lofs] ) break;
-                               img->draw_pixel(i, y);
                                msk[lofs] = 0xff;  lt = i;
                        }
                        int rofs = ofs;
                        for( int i=rt; ++i< w; ) {
+                               draw_pixel(i, y);
                                if( msk[++rofs] ) break;
-                               img->draw_pixel(i, y);
                                msk[rofs] = 0xff;  rt = i;
                        }
                        if( y+1 <  h ) push(y+1, lt, rt);
@@ -629,12 +648,13 @@ SketcherPoint *FillRegion::next()
        return 0;
 }
 
-
-void SketcherCurve::draw(VFrame *img)
+void SketcherCurve::draw(VFrame *img, int alias)
 {
        if( !points.size() ) return;
+       img->set_pixel_color(color, (~color>>24)&0xff);
        const float fmx = 16383;
        SketcherVPen *vpen = new_vpen(img);
+       vpen->set_draw_flags(alias);
        FillRegion fill(points, vpen);
        SketcherPoint *pnt0 = fill.next();
        SketcherPoint *pnt1 = pnt0 ? fill.next() : 0;
@@ -694,7 +714,7 @@ void SketcherCurve::draw(VFrame *img)
                vpen->draw_line(pnt0->x, pnt0->y, pnt1->x, pnt1->y);
        }
        else if( pnt0 ) {
-               vpen->draw_pixel(pnt0->x, pnt0->y);
+               vpen->draw_pixel(pnt0->x, pnt0->y, 1);
        }
        delete vpen;
 }
@@ -740,10 +760,11 @@ int Sketcher::process_realtime(VFrame *input, VFrame *output)
                int m = cv->points.size();
                if( !m ) continue;
                img->clear_frame();
-               img->set_pixel_color(cv->color, (~cv->color>>24)&0xff);
-               cv->draw(img);
+               int alias = config.aliasing < 0 ? ALIAS_OFF :
+                       config.aliasing > 0 ? ALIAS_DBL : ALIAS_NRM;
+               cv->draw(img, alias);
                overlay_frame->overlay(out, img, 0,0,w,h, 0,0,w,h,
-                               1.f, TRANSFER_NORMAL, NEAREST_NEIGHBOR);
+                               1.f, TRANSFER_SRC_OVER, NEAREST_NEIGHBOR);
        }
 
        if( config.drag ) {
index 1ddd5a478635d795b1dc3d441e861cce29078100..dcf7a6ba34772c08e92312ed311c23ce4e43e4f0 100644 (file)
@@ -46,6 +46,7 @@ public:
        int n;
        uint8_t *msk;
 
+       int draw_mask(int x, int y);
        SketcherVPen(VFrame *vfrm, int n)
         : VFrame(vfrm->get_data(), -1, vfrm->get_y()-vfrm->get_data(),
            vfrm->get_u()-vfrm->get_data(), vfrm->get_v()-vfrm->get_data(),
@@ -57,40 +58,38 @@ public:
        }
        ~SketcherVPen() { delete [] msk; }
 
-       void draw_line(float x1, float y1, float x2, float y2) {
-               VFrame::draw_line(int(x1+.5f),int(y1+.5f), int(x2+.5f),int(y2+.5f));
-       }
        void draw_smooth(float x1, float y1, float x2, float y2, float x3, float y3) {
                VFrame::draw_smooth(int(x1+.5f),int(y1+.5f),
                        int(x2+.5f),int(y2+.5f), int(x3+.5f),int(y3+.5f));
        }
 
-       virtual int draw_pixel(int x, int y) = 0;
+       virtual int draw_pixel(float x, float y, float a) = 0;
+       int draw_pixel(float x, float y, float frac, int axis);
 };
 
 class SketcherPenSquare : public SketcherVPen
 {
 public:
        SketcherPenSquare(VFrame *vfrm, int n) : SketcherVPen(vfrm, n) {}
-       int draw_pixel(int x, int y);
+       int draw_pixel(float x, float y, float a);
 };
 class SketcherPenPlus : public SketcherVPen
 {
 public:
        SketcherPenPlus(VFrame *vfrm, int n) : SketcherVPen(vfrm, n) {}
-       int draw_pixel(int x, int y);
+       int draw_pixel(float x, float y, float a);
 };
 class SketcherPenSlant : public SketcherVPen
 {
 public:
        SketcherPenSlant(VFrame *vfrm, int n) : SketcherVPen(vfrm, n) {}
-       int draw_pixel(int x, int y);
+       int draw_pixel(float x, float y, float a);
 };
 class SketcherPenXlant : public SketcherVPen
 {
 public:
        SketcherPenXlant(VFrame *vfrm, int n) : SketcherVPen(vfrm, n) {}
-       int draw_pixel(int x, int y);
+       int draw_pixel(float x, float y, float a);
 };
 
 
@@ -140,7 +139,7 @@ public:
        double nearest_point(int &pi, coord x, coord y);
 
        SketcherVPen *new_vpen(VFrame *out);
-       void draw(VFrame *img);
+       void draw(VFrame *img, int flags);
 };
 class SketcherCurves : public ArrayList<SketcherCurve *>
 {
@@ -166,6 +165,7 @@ public:
        void dump();
 
        int drag;
+       int aliasing;
        int cv_selected, pt_selected;
 };
 
index f62802a73abc048eef894c6a50f70fc22bc3ad97..ff97dd14dc14343348ec09cb8cee330319fbd786 100644 (file)
@@ -255,8 +255,52 @@ void SketcherCurveWidth::update(int width)
 }
 
 
+SketcherAliasItem::SketcherAliasItem(SketcherAliasing *popup, int v)
+ : BC_MenuItem(popup->alias_to_text(v))
+{
+       this->popup = popup;
+       this->v = v;
+}
+
+int SketcherAliasItem::handle_event()
+{
+       popup->set_text(get_text());
+       popup->plugin->config.aliasing = v;
+       popup->gui->send_configure_change();
+       return 1;
+}
+
+
+SketcherAliasing::SketcherAliasing(SketcherWindow *gui, Sketcher *plugin,
+               int x, int y)
+ : BC_PopupMenu(x, y, xS(64),
+               alias_to_text(plugin->config.aliasing), 1, 0, xS(3))
+{
+       this->gui = gui;
+       this->plugin = plugin;
+}
+SketcherAliasing::~SketcherAliasing()
+{
+}
+
+void SketcherAliasing::create_objects()
+{
+       add_item(new SketcherAliasItem(this, -1));
+       add_item(new SketcherAliasItem(this, 0));
+       add_item(new SketcherAliasItem(this, 1));
+}
+
+const char *SketcherAliasing::alias_to_text(int alias)
+{
+       if( alias < 0 ) return _("Off");
+       if( alias > 0 ) return _("Dbl");
+       return _("On");
+}
+
+
+
 SketcherWindow::SketcherWindow(Sketcher *plugin)
- : PluginClientWindow(plugin, xS(380), yS(620), xS(380), yS(620), 0)
+ : PluginClientWindow(plugin, xS(400), yS(620), xS(400), yS(620), 0)
 {
        this->plugin = plugin;
        this->title_pen = 0;  this->curve_pen = 0;
@@ -310,6 +354,10 @@ void SketcherWindow::create_objects()
        x1 += title_width->get_w() + margin;
        curve_width = new SketcherCurveWidth(this, x1, y, cv->width);
        curve_width->create_objects();
+       x1 += curve_width->get_w() + margin;
+       aliasing = new SketcherAliasing(this, plugin, x1, y);
+       add_subwindow(aliasing);        dy = bmax(dy,aliasing->get_h());
+       aliasing->create_objects();
        y += dy + 2*margin;             dy = 0;
 
        x1 = get_w()-x - BC_Title::calculate_w(this, curve_text, LARGEFONT);
index 615852010129ec536df58100387578ada1192d54..72fcc166be25ad6e6d1579891d9690eeee571688 100644 (file)
@@ -15,7 +15,6 @@
  * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  */
 
 #ifndef __SKETCHERWINDOW_H__
@@ -38,6 +37,8 @@ class SketcherDelCurve;
 class SketcherCurveUp;
 class SketcherCurveDn;
 class SketcherCurveWidth;
+class SketcherAliasItem;
+class SketcherAliasing;
 class SketcherCurveList;
 class SketcherPointX;
 class SketcherPointY;
@@ -168,6 +169,30 @@ public:
        int width;
 };
 
+class SketcherAliasItem : public BC_MenuItem
+{
+public:
+       SketcherAliasItem(SketcherAliasing *popup, int v);
+       int handle_event();
+
+       SketcherAliasing *popup;
+       int v;
+};
+
+class SketcherAliasing : public BC_PopupMenu
+{
+public:
+       SketcherAliasing(SketcherWindow *gui, Sketcher *plugin,
+                       int x, int y);
+       ~SketcherAliasing();
+
+       const char *alias_to_text(int alias);
+       void create_objects();
+
+       Sketcher *plugin;
+       SketcherWindow *gui;
+};
+
 class SketcherCurveList : public BC_ListBox
 {
 public:
@@ -376,6 +401,7 @@ public:
        SketcherCurveUp *curve_up;
        SketcherCurveDn *curve_dn;
        SketcherCurveWidth *curve_width;
+       SketcherAliasing *aliasing;
        SketcherCurveList *curve_list;
        SketcherResetCurves *reset_curves;
 
index cff7659854c4864c5ce0a6fe3b838724a19e2235..ccc04709814e9d08eb7a93e791f41ffe714ee13f 100644 (file)
@@ -85,7 +85,7 @@ int TracerPointY::handle_event()
 }
 
 TracerWindow::TracerWindow(Tracer *plugin)
- : PluginClientWindow(plugin, xS(400), yS(420), xS(400), yS(420), 0)
+ : PluginClientWindow(plugin, xS(460), yS(420), xS(460), yS(420), 0)
 {
        this->plugin = plugin;
        this->title_x = 0;    this->point_x = 0;
@@ -116,18 +116,18 @@ void TracerWindow::create_objects()
        TracerPoint *pt = hot_point >= 0 ? plugin->config.points[hot_point] : 0;
        point_x = new TracerPointX(this, x1, y, !pt ? 0 : pt->x);
        point_x->create_objects();
-       x1 += point_x->get_w() + margin;
+       x1 += point_x->get_w() + margin + xS(20);
        add_subwindow(new_point = new TracerNewPoint(this, plugin, x1, y));
-       x1 += new_point->get_w() + margin;
+       x1 += new_point->get_w() + margin + xS(30);
        add_subwindow(point_up = new TracerPointUp(this, x1, y));
        y += point_x->get_h() + margin;
        add_subwindow(title_y = new BC_Title(x, y, _("Y:")));
        x1 = x + title_y->get_w() + margin;
        point_y = new TracerPointY(this, x1, y, !pt ? 0 : pt->y);
        point_y->create_objects();
-       x1 += point_y->get_w() + margin;
+       x1 += point_y->get_w() + margin + xS(20);
        add_subwindow(del_point = new TracerDelPoint(this, plugin, x1, y));
-       x1 += del_point->get_w() + margin;
+       x1 += del_point->get_w() + margin + xS(30);
        add_subwindow(point_dn = new TracerPointDn(this, x1, y));
        y += point_y->get_h() + margin + yS(10);
 
@@ -595,7 +595,7 @@ int TracerRadius::handle_event()
 }
 
 TracerNewPoint::TracerNewPoint(TracerWindow *gui, Tracer *plugin, int x, int y)
- : BC_GenericButton(x, y, xS(80), _("New"))
+ : BC_GenericButton(x, y, xS(100), _("New"))
 {
        this->gui = gui;
        this->plugin = plugin;
@@ -612,7 +612,7 @@ int TracerNewPoint::handle_event()
 }
 
 TracerDelPoint::TracerDelPoint(TracerWindow *gui, Tracer *plugin, int x, int y)
- : BC_GenericButton(x, y, xS(80), C_("Del"))
+ : BC_GenericButton(x, y, xS(100), C_("Del"))
 {
        this->gui = gui;
        this->plugin = plugin;
index 2712b26040192d695144f7db4de1df39e10ad33c..511d462499a82cf67301e9a9042b5753000116fc 100644 (file)
@@ -986,7 +986,7 @@ msgstr "Recursos"
 #: cinelerra/awindowgui.C:1428 cinelerra/awindowgui.C:2364
 #: cinelerra/awindowgui.C:2384
 msgid "awindowgui#Title"
-msgstr "awindowgui#Título"
+msgstr "Título"
 
 #: cinelerra/awindowgui.C:1429 cinelerra/awindowgui.C:2365
 msgid "Comments"
@@ -1991,7 +1991,7 @@ msgstr "Fuente"
 
 #: cinelerra/channelinfo.C:347
 msgid "channelinfo#Title"
-msgstr "channelinfo#Título"
+msgstr "Título"
 
 #: cinelerra/channelinfo.C:348 cinelerra/dbwindow.C:596
 #: cinelerra/recordbatches.C:22
@@ -2188,43 +2188,43 @@ msgstr "Selector de color"
 
 #: cinelerra/colorpicker.C:179
 msgid "colorpicker#H:"
-msgstr "colorpicker#H:"
+msgstr "H:"
 
 #: cinelerra/colorpicker.C:180
 msgid "colorpicker#S:"
-msgstr "colorpicker#S:"
+msgstr "S:"
 
 #: cinelerra/colorpicker.C:181
 msgid "colorpicker_value#V:"
-msgstr "colorpicker_value#V:"
+msgstr "V:"
 
 #: cinelerra/colorpicker.C:182
 msgid "colorpicker#R:"
-msgstr "colorpicker#R:"
+msgstr "R:"
 
 #: cinelerra/colorpicker.C:183
 msgid "colorpicker#G:"
-msgstr "colorpicker#G:"
+msgstr "G:"
 
 #: cinelerra/colorpicker.C:184
 msgid "colorpicker#B:"
-msgstr "colorpicker#B:"
+msgstr "B:"
 
 #: cinelerra/colorpicker.C:185
 msgid "colorpicker#Y:"
-msgstr "colorpicker#Y:"
+msgstr "Y:"
 
 #: cinelerra/colorpicker.C:186
 msgid "colorpicker#U:"
-msgstr "colorpicker#U:"
+msgstr "U:"
 
 #: cinelerra/colorpicker.C:187
 msgid "colorpicker_Cr#V:"
-msgstr "colorpicker_Cr#V:"
+msgstr "V:"
 
 #: cinelerra/colorpicker.C:189
 msgid "colorpicker#A:"
-msgstr "colorpicker#A:"
+msgstr "A:"
 
 #: cinelerra/colorpicker.C:205
 msgid "Hue"
@@ -3026,7 +3026,7 @@ msgstr "longitud"
 
 #: cinelerra/dbwindow.C:595
 msgid "dbwindow#Title"
-msgstr "dbwindow#Título"
+msgstr "Título"
 
 #: cinelerra/dbwindow.C:597
 msgid "Access time"
@@ -5585,7 +5585,7 @@ msgstr "Aplicar a todos los fotogramas clave seleccionados"
 
 #: cinelerra/keyframegui.C:761
 msgid "keyframegui#Save"
-msgstr "keyframegui#Guardar"
+msgstr "Guardar"
 
 #: cinelerra/keyframepopup.C:103
 msgid "Show Plugin Settings"
@@ -10244,7 +10244,7 @@ msgstr "Arrastrar"
 
 #: plugins/crikey/crikeywindow.C:610
 msgid "crikeywindow#Del"
-msgstr "crikeywindow#Borrar"
+msgstr "Borrar"
 
 #: plugins/crop/crop.C:143
 msgid "Crop & Position"
@@ -12583,7 +12583,7 @@ msgstr "pluma"
 
 #: plugins/sketcher/sketcherwindow.C:859 plugins/sketcher/sketcherwindow.C:1234
 msgid "sketcherwindow#Del"
-msgstr "sketcherwindow#Supr"
+msgstr "Borrar"
 
 #: plugins/sketcher/sketcherwindow.C:992
 msgid "Type"
@@ -12923,7 +12923,7 @@ msgstr "Máscara Alpha"
 
 #: plugins/timefront/timefront.C:513
 msgid "timefront#Square"
-msgstr "timefront#Cuadrado"
+msgstr "Cuadrado"
 
 #: plugins/timefront/timefront.C:599
 msgid "Inversion"
@@ -13216,7 +13216,7 @@ msgstr "Rellenar"
 
 #: plugins/tracer/tracerwindow.C:615
 msgid "tracerwindow#Del"
-msgstr "tracerwindow#Supr"
+msgstr "Borrar"
 
 #: plugins/translate/translatewin.C:61
 msgid "In X:"