split resource_thread update into separate audio/video threads, boxblur layout tweaks
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mwindowgui.C
index 70c4808a959ea8b8c25a72b13fc6abb471ef0227..7b92aa3258ae2a6635b163b0aaaff3a80329e418 100644 (file)
@@ -36,6 +36,7 @@
 #include "edl.h"
 #include "edlsession.h"
 #include "filesystem.h"
+#include "filexml.h"
 #include "keyframepopup.h"
 #include "keys.h"
 #include "language.h"
@@ -58,6 +59,7 @@
 #include "record.h"
 #include "recordgui.h"
 #include "renderengine.h"
+#include "remotecontrol.h"
 #include "resourcethread.h"
 #include "samplescroll.h"
 #include "shbtnprefs.h"
 #include "swindow.h"
 #include "theme.h"
 #include "trackcanvas.h"
+#include "trackpopup.h"
 #include "trackscroll.h"
 #include "tracks.h"
 #include "transitionpopup.h"
 #include "vwindowgui.h"
 #include "vwindow.h"
+#include "wintv.h"
+#include "x10tv.h"
 #include "zoombar.h"
 
 #define PANE_DRAG_MARGIN MAX(mwindow->theme->pane_w, mwindow->theme->pane_h)
 // the main window uses its own private colormap for video
 MWindowGUI::MWindowGUI(MWindow *mwindow)
  : BC_Window(_(PROGRAM_NAME ": Program"),
-               mwindow->session->mwindow_x,
-               mwindow->session->mwindow_y,
-               mwindow->session->mwindow_w,
-               mwindow->session->mwindow_h,
-               100,
-               100,
-               1,
-               1,
-               1)
+               mwindow->session->mwindow_x, mwindow->session->mwindow_y,
+               mwindow->session->mwindow_w, mwindow->session->mwindow_h,
+               xS(100), yS(100), 1, 1, 1)
 {
        this->mwindow = mwindow;
 //     samplescroll = 0;
@@ -104,6 +103,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;
 
@@ -116,12 +116,13 @@ MWindowGUI::MWindowGUI(MWindow *mwindow)
        statusbar = 0;
        zoombar = 0;
        mainclock = 0;
+       track_menu = 0;
        edit_menu = 0;
        plugin_menu = 0;
        keyframe_menu = 0;
        keyframe_hide = 0;
        keyvalue_popup = 0;
-       transition_menu = 0;
+       transition_menu = 0;
        remote_control = 0;
        cwindow_remote_handler = 0;
        record_remote_handler = 0;
@@ -153,134 +154,61 @@ MWindowGUI::~MWindowGUI()
        delete y_divider;
 }
 
-#if 0
-void MWindowGUI::get_scrollbars(int flush)
-{
-       //int64_t h_needed = mwindow->edl->get_tracks_height(mwindow->theme);
-       //int64_t w_needed = mwindow->edl->get_tracks_width();
-       int need_xscroll = 0;
-       int need_yscroll = 0;
-       view_w = mwindow->theme->mcanvas_w;
-       view_h = mwindow->theme->mcanvas_h;
-
-// Scrollbars are constitutive
-       need_xscroll = need_yscroll = 1;
-       view_h = mwindow->theme->mcanvas_h;
-       view_w = mwindow->theme->mcanvas_w;
-
-//     for(int i = 0; i < 2; i++)
-//     {
-//             if(w_needed > view_w)
-//             {
-//                     need_xscroll = 1;
-//                     view_h = mwindow->theme->mcanvas_h - SCROLL_SPAN;
-//             }
-//             else
-//                     need_xscroll = 0;
-//
-//             if(h_needed > view_h)
-//             {
-//                     need_yscroll = 1;
-//                     view_w = mwindow->theme->mcanvas_w - SCROLL_SPAN;
-//             }
-//             else
-//                     need_yscroll = 0;
-//     }
-//printf("MWindowGUI::get_scrollbars 1\n");
-
-       if(canvas && (view_w != canvas->get_w() || view_h != canvas->get_h()))
-       {
-               canvas->reposition_window(mwindow->theme->mcanvas_x,
-                       mwindow->theme->mcanvas_y,
-                       view_w,
-                       view_h);
-       }
-
-       if(need_xscroll)
-       {
-               if(!samplescroll)
-                       add_subwindow(samplescroll = new SampleScroll(mwindow,
-                               this,
-                               mwindow->theme->mhscroll_x,
-                               mwindow->theme->mhscroll_y,
-                               mwindow->theme->mhscroll_w));
-               else
-                       samplescroll->resize_event();
-
-               samplescroll->set_position(0);
-       }
-       else
-       {
-               if(samplescroll) delete samplescroll;
-               samplescroll = 0;
-               mwindow->edl->local_session->view_start = 0;
-       }
-
-
-       if(need_yscroll)
-       {
-//printf("MWindowGUI::get_scrollbars 1.1 %p %p\n", this, canvas);
-               if(!trackscroll)
-                       add_subwindow(trackscroll = new TrackScroll(mwindow,
-                               this,
-                               mwindow->theme->mvscroll_x,
-                               mwindow->theme->mvscroll_y,
-                               mwindow->theme->mvscroll_h));
-               else
-                       trackscroll->resize_event();
-
-
-//printf("MWindowGUI::get_scrollbars 1.2\n");
-               trackscroll->update_length(mwindow->edl->get_tracks_height(mwindow->theme),
-                       mwindow->edl->local_session->track_start,
-                       view_h,
-                       0);
-//printf("MWindowGUI::get_scrollbars 1.3\n");
-       }
-       else
-       {
-               if(trackscroll) delete trackscroll;
-               trackscroll = 0;
-               mwindow->edl->local_session->track_start = 0;
-       }
-
-       if(flush) this->flush();
-
-}
-#endif // 0
-
 void MWindowGUI::create_objects()
 {
        lock_window("MWindowGUI::create_objects");
        const int debug = 0;
 
-       resource_thread = new ResourceThread(mwindow, this);
+       resource_thread = new ResourceThread(mwindow);
        resource_thread->create_objects();
 
 
        if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
        set_icon(mwindow->theme->get_image("mwindow_icon"));
        remote_control = new RemoteControl(this);
-       cwindow_remote_handler = new CWindowRemoteHandler(remote_control);
-       record_remote_handler = new RecordRemoteHandler(remote_control);
+       cwindow_remote_handler = 0;
+       record_remote_handler = 0;
+#ifdef HAVE_X10TV
+// should be first, use if plugged
+       if( !cwindow_remote_handler && mwindow->x10tv ) {
+               cwindow_remote_handler = (RemoteHandler*)
+                       new X10TVCWindowHandler(mwindow->x10tv, remote_control);
+               record_remote_handler = (RemoteHandler*)
+                       new X10TVRecordHandler(mwindow->x10tv, remote_control);
+       }
+#endif
+#ifdef HAVE_WINTV
+       if( !cwindow_remote_handler && mwindow->wintv ) {
+               cwindow_remote_handler = (RemoteHandler*)
+                       new WinTVCWindowHandler(mwindow->wintv, remote_control);
+               record_remote_handler = (RemoteHandler*)
+                       new WinTVRecordHandler(mwindow->wintv, remote_control);
+       }
+#endif
        mwindow->reset_android_remote();
-
+       if( !cwindow_remote_handler )
+               cwindow_remote_handler = (RemoteHandler*)
+                       new CWindowKeyEvHandler(mwindow->gui->remote_control);
+       if( !record_remote_handler )
+               record_remote_handler = (RemoteHandler*)
+                       new RecordKeyEvHandler(mwindow->gui->remote_control);
        if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
 
-       int x = get_w() - MainShBtns::calculate_w(0);
-       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()+2;
-       add_subwindow(proxy_toggle = new ProxyToggle(mwindow, mbuttons, x1, y1));
-       x1 += proxy_toggle->get_w() + 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,
@@ -291,26 +219,6 @@ void MWindowGUI::create_objects()
                mwindow->theme->mcanvas_h);
        pane[TOP_LEFT_PANE]->create_objects();
 
-//     add_subwindow(timebar = new MTimeBar(mwindow,
-//             this,
-//             mwindow->theme->mtimebar_x,
-//             mwindow->theme->mtimebar_y,
-//             mwindow->theme->mtimebar_w,
-//             mwindow->theme->mtimebar_h));
-//     timebar->create_objects();
-
-//     if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
-//     add_subwindow(patchbay = new PatchBay(mwindow, this));
-//     patchbay->create_objects();
-
-//     if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
-//     get_scrollbars(0);
-
-//     if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
-//     mwindow->gui->add_subwindow(canvas = new TrackCanvas(mwindow, this));
-//     canvas->create_objects();
-
-
        if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
        add_subwindow(zoombar = new ZoomBar(mwindow, this));
        zoombar->create_objects();
@@ -336,6 +244,9 @@ void MWindowGUI::create_objects()
 //     cursor->create_objects();
 
 
+       if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
+       add_subwindow(track_menu = new TrackPopup(mwindow, this));
+       track_menu->create_objects();
        if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
        add_subwindow(edit_menu = new EditPopup(mwindow, this));
        edit_menu->create_objects();
@@ -405,15 +316,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(0);
-       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()+2;
-       proxy_toggle->reposition_window(x1, y1);
-       x1 += proxy_toggle->get_w() + 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();
@@ -698,28 +610,17 @@ void MWindowGUI::draw_indexes(Indexable *indexable)
        }
 }
 
-void MWindowGUI::draw_canvas(int mode /* = 0 */, int hide_cursor /* = 1 */)
+void MWindowGUI::draw_canvas(int redraw, int hide_cursor)
 {
-       if(mode != IGNORE_THREAD)
-       {
-               resource_thread->stop_draw(1);
-       }
-
+       resource_thread->stop_draw(0);
 
-       for(int i = 0; i < TOTAL_PANES; i++)
-       {
-               if(pane[i])
-               {
+       int mode = redraw ? FORCE_REDRAW : NORMAL_DRAW;
+       for(int i = 0; i < TOTAL_PANES; i++) {
+               if( pane[i] )
                        pane[i]->canvas->draw(mode, hide_cursor);
-               }
-       }
-
-
-       if(mode != IGNORE_THREAD)
-       {
-               resource_thread->start_draw();
        }
 
+       resource_thread->start_draw();
 }
 
 void MWindowGUI::flash_canvas(int flush)
@@ -736,6 +637,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;
 }
@@ -801,7 +703,7 @@ void MWindowGUI::update_scrollbars(int flush)
        {
                if(pane[i])
                {
-                       pane[i]->update(1, 0, 0, 0);
+                       pane[i]->update(1, NO_DRAW, 0, 0);
                }
        }
        if(flush) this->flush();
@@ -877,10 +779,8 @@ void MWindowGUI::update(int scrollbars,
 
        mwindow->edl->tracks->update_y_pixels(mwindow->theme);
 
-       if(do_canvas && do_canvas != IGNORE_THREAD)
-       {
+       if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
                resource_thread->stop_draw(1);
-       }
 
        for(int i = 0; i < TOTAL_PANES; i++)
        {
@@ -890,10 +790,8 @@ void MWindowGUI::update(int scrollbars,
                        patchbay);
        }
 
-       if(do_canvas && do_canvas != IGNORE_THREAD)
-       {
+       if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
                resource_thread->start_draw();
-       }
 
 //     if(scrollbars) this->get_scrollbars(0);
 //     if(timebar) this->timebar->update(0);
@@ -923,8 +821,7 @@ void MWindowGUI::update(int scrollbars,
 
 // Can't age if the cache called this to draw missing picons
 // or the GUI is updating the status of the draw toggle.
-       if(do_canvas != FORCE_REDRAW && do_canvas != IGNORE_THREAD)
-       {
+       if( do_canvas != FORCE_REDRAW && do_canvas != IGNORE_THREAD ) {
                unlock_window();
                mwindow->age_caches();
                lock_window("MWindowGUI::update");
@@ -942,9 +839,9 @@ int MWindowGUI::visible(int64_t x1, int64_t x2, int64_t view_x1, int64_t view_x2
 }
 
 
-void MWindowGUI::show_message(const char *message, int color)
+void MWindowGUI::show_message(const char *message, int msg_color, int bar_color)
 {
-       statusbar->show_message(message, color);
+       statusbar->show_message(message, msg_color, bar_color);
 }
 
 void MWindowGUI::update_default_message()
@@ -1018,11 +915,11 @@ int MWindowGUI::drag_motion()
 
        if( mwindow->session->current_operation == DRAG_ASSET ||
            mwindow->session->current_operation == DRAG_EDIT ||
+           mwindow->session->current_operation == DRAG_GROUP ||
            mwindow->session->current_operation == DRAG_AEFFECT_COPY ||
-           mwindow->session->current_operation == DRAG_VEFFECT_COPY )
-        {
-                redraw = 1;
-        }
+           mwindow->session->current_operation == DRAG_VEFFECT_COPY ) {
+               redraw = 1;
+       }
 
 
 // printf("drag_motion %d %d over_track=%p over_edit=%p\n",
@@ -1181,9 +1078,27 @@ int MWindowGUI::keypress_event()
        int result = mbuttons->keypress_event();
        if( result ) return result;
 
-       Track *this_track = 0;
+       Track *this_track = 0, *first_track = 0;
+       int collapse = 0, packed = 0, overwrite = 0, plugins = 0;
+       double position = 0;
+
+       switch( get_keypress() ) {
+       case 'A':
+               if( !alt_down() ) {
+                       if( !ctrl_down() || !shift_down() ) break;
+                       mwindow->edl->tracks->clear_selected_edits();
+                       draw_overlays(1);
+                       result = 1;
+                       break;
+               } // fall thru
+       case 'a':
+               if( !alt_down() ) break;
+               stop_transport("MWindowGUI::keypress_event 1");
+               mwindow->nearest_auto_keyframe(shift_down(),
+                       !ctrl_down() ? PLAY_FORWARD : PLAY_REVERSE);
+               result = 1;
+               break;
 
-       switch(get_keypress()) {
        case 'e':
                mwindow->toggle_editing_mode();
                result = 1;
@@ -1191,14 +1106,65 @@ int MWindowGUI::keypress_event()
 
        case 'k': case 'K':
                if( alt_down() ) break;
-               stop_transport("MWindowGUI::keypress_event 1");
+               stop_transport("MWindowGUI::keypress_event 2");
                mwindow->nearest_plugin_keyframe(shift_down(),
                        !ctrl_down() ? PLAY_FORWARD : PLAY_REVERSE);
                result = 1;
                break;
 
-       case '1': case '2': case '3': case '4':
-       case '5': case '6': case '7': case '8':
+       case 'C':
+               packed = 1;
+       case 'c':
+               if( !ctrl_down() || alt_down() ) break;
+               mwindow->selected_edits_to_clipboard(packed);
+               result = 1;
+               break;
+       case 'P':
+               plugins = 1;
+       case 'b':
+               overwrite = -1; // fall thru
+       case 'v':
+               if( !ctrl_down() || alt_down() ) break;
+               if( mwindow->session->current_operation == DROP_TARGETING ) {
+                       mwindow->session->current_operation = NO_OPERATION;
+                       mwindow->gui->set_editing_mode(1);
+                       int pane_no = 0;
+                       for( ; pane_no<TOTAL_PANES; ++pane_no  ) {
+                               if( !pane[pane_no] ) continue;
+                               first_track = pane[pane_no]->over_track();
+                               if( first_track ) break;
+                       }
+                       if( first_track ) {
+                               int cursor_x = pane[pane_no]->canvas->get_relative_cursor_x();
+                               position = mwindow->edl->get_cursor_position(cursor_x, pane_no);
+                       }
+               }
+               else
+                       position = mwindow->edl->local_session->get_selectionstart();
+               if( !plugins )
+                       mwindow->paste(position, first_track, 0, overwrite);
+               else
+                       mwindow->paste_clipboard(first_track, position, 1, 0, 1, 1, 1);
+               mwindow->edl->tracks->clear_selected_edits();
+               draw_overlays(1);
+               result = 1;
+               break;
+       case 'M':
+               collapse = 1;
+       case BACKSPACE:
+       case 'm':
+               mwindow->cut_selected_edits(0, collapse);
+               result = 1;
+               break;
+       case 'z':
+               collapse = 1;
+       case 'x':
+               if( !ctrl_down() || alt_down() ) break;
+               mwindow->cut_selected_edits(1, collapse);
+               result = 1;
+               break;
+
+       case '1' ... '8':
                if( !alt_down() || shift_down() ) break;
                if( !mwindow->select_asset(get_keypress()-'1',1) )
                        result = 1;
@@ -1304,7 +1270,7 @@ int MWindowGUI::keypress_event()
                        if( !selected && this_track ) this_track->record = 1;
                }
 
-               update(0, 1, 0, 0, 1, 0, 1);
+               update(0, NORMAL_DRAW, 0, 0, 1, 0, 1);
                unlock_window();
                mwindow->cwindow->update(0, 1, 1);
                lock_window("MWindowGUI::keypress_event 3");
@@ -1312,18 +1278,7 @@ int MWindowGUI::keypress_event()
                result = 1;
                break;
 
-       case KEY_F1:
-       case KEY_F2:
-       case KEY_F3:
-       case KEY_F4:
-       case KEY_F5:
-       case KEY_F6:
-       case KEY_F7:
-       case KEY_F8:
-       case KEY_F9:
-       case KEY_F10:
-       case KEY_F11:
-       case KEY_F12:
+       case KEY_F1 ... KEY_F12:
                resend_event(mwindow->cwindow->gui);
                return 1;
        }
@@ -1380,6 +1335,19 @@ void MWindowGUI::use_android_remote(int on)
        if( android_control ) return;
        android_control = new AndroidControl(this);
 }
+int MWindowGUI::keyev_grab_remote()
+{
+       if( cwindow_remote_handler && cwindow_remote_handler->is_keytv() &&
+           record_remote_handler  && record_remote_handler->is_keytv() )
+               return 0;
+       delete cwindow_remote_handler;
+       delete record_remote_handler;
+       cwindow_remote_handler = (RemoteHandler*)
+               new CWindowKeyEvHandler(mwindow->gui->remote_control);
+       record_remote_handler = (RemoteHandler*)
+               new RecordKeyEvHandler(mwindow->gui->remote_control);
+       return 1;
+}
 
 int MWindowGUI::close_event()
 {
@@ -1841,8 +1809,9 @@ void MWindowGUI::delete_y_pane(int cursor_y)
 
 void MWindowGUI::stop_pane_drag()
 {
+       if( !dragging_pane ) return;
        dragging_pane = 0;
-       resource_thread->stop_draw(1);
+       resource_thread->stop_draw(0);
 
        if(x_pane_drag)
        {
@@ -2310,7 +2279,7 @@ void MWindowGUI::stop_transport(const char *lock_msg)
 {
        if( !mbuttons->transport->is_stopped() ) {
                if( lock_msg ) unlock_window();
-               mbuttons->transport->handle_transport(STOP, 1, 0, 0);
+               mbuttons->transport->handle_transport(STOP, 1);
                if( lock_msg ) lock_window(lock_msg);
        }
 }
@@ -2375,13 +2344,37 @@ int FFMpegToggle::handle_event()
        set_tooltip(ffmpeg_early_probe ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
        mwindow->preferences->set_file_probe_armed("FFMPEG_Early", ffmpeg_early_probe);
        mwindow->preferences->set_file_probe_armed("FFMPEG_Late", !ffmpeg_early_probe);
-
+       mwindow->update_preferences(mwindow->preferences);
        mwindow->show_warning(&mwindow->preferences->warn_indexes,
                _("Changing the base codecs may require rebuilding indexes."));
        return 1;
 }
 
 
+StackButton::StackButton(MWindow *mwindow, int x, int y)
+ : BC_GenericButton(x, y, mwindow->theme->stack_button_w, "0")
+{
+       this->mwindow = mwindow;
+       set_tooltip(_("Close EDL"));
+}
+
+int StackButton::handle_event()
+{
+       mwindow->save_backup();
+       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();
+}
+
+
 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 :
@@ -2420,10 +2413,12 @@ ProxyToggle::~ProxyToggle()
 int ProxyToggle::handle_event()
 {
        int disabled = get_value();
+       mwindow->gui->unlock_window();
        if( disabled )
                mwindow->disable_proxy();
        else
                mwindow->enable_proxy();
+       mwindow->gui->lock_window("ProxyToggle::handle_event");
        set_tooltip(!disabled ? _("Disable proxy") : _("Enable proxy"));
        return 1;
 }