Yippie! fixed block size rendering, slower but way more flexibe - Alex
authorterminatorX <>
Tue, 25 Mar 2003 00:02:05 +0000 (00:02 +0000)
committerterminatorX <>
Tue, 25 Mar 2003 00:02:05 +0000 (00:02 +0000)
13 files changed:
src/main.cc
src/tX_audiodevice.cc
src/tX_audiodevice.h
src/tX_dialog.cc
src/tX_engine.cc
src/tX_engine.h
src/tX_glade_interface.cc
src/tX_mastergui.cc
src/tX_midiin.cc
src/tX_vtt.cc
src/tX_vtt.h
src/tX_vttgui.cc
terminatorX.glade

index 6adb227e3e30a1c7df58d6608b05da0af22c50e4..011f8a89dee96850a02f79c08244e67f52cb7ea5 100644 (file)
@@ -367,7 +367,7 @@ int main(int argc, char **argv)
        fprintf(stderr, "%s - Copyright (C) 1999-2003 by Alexander K├Ânig\n", VERSIONSTRING);
        fprintf(stderr, "terminatorX comes with ABSOLUTELY NO WARRANTY - for details read the license.\n");
 
-       engine=new tX_engine();
+       tX_engine *engine=tX_engine::get_instance();
        
 #ifdef USE_3DNOW
        if (tx_mm_support()!=5) {
index a740a37bdb9174003079dc03bf49794e009fd070..a641d62c4c7c81b711552ec8d6a5f463e03c0d54 100644 (file)
@@ -24,6 +24,7 @@
 #define ALSA_PCM_NEW_HW_PARAMS_API
 
 #include "tX_audiodevice.h"
+#include "tX_vtt.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
+#include "tX_engine.h"
 
-void tX_audiodevice :: init()
+tX_audiodevice :: tX_audiodevice() : samples_per_buffer(0),
+current_buffer(0), buffer_pos(0)
 {
-       samples_per_buffer=0;
-       //set_buffersize_near(globals.audiodevice_buffersize);
+       sample_buffer[0]=NULL;
+       sample_buffer[1]=NULL;
+       engine=tX_engine::get_instance();
 }
 
+void tX_audiodevice :: start() {
+       sample_buffer[0]=new int16_t[samples_per_buffer*2];
+       sample_buffer[1]=new int16_t[samples_per_buffer*2];
+       int current=0;
+       
+       while (!engine->is_stopped()) {
+               current=current ? 0 : 1;
+               
+               int16_t *current_buffer=sample_buffer[current];
+               int16_t *next_buffer=sample_buffer[current ? 0 : 1];
+               
+               fill_buffer(current_buffer, next_buffer);
+               play(current_buffer);
+       }
+       
+       delete [] sample_buffer[0];
+       delete [] sample_buffer[1];
+}
+
+void tX_audiodevice :: fill_buffer(int16_t *target_buffer, int16_t *next_target_buffer) {
+       int vtt_buffer_size=vtt_class::get_mix_buffer_size()<<1;
+       int prefill;
+       
+       while (buffer_pos < samples_per_buffer) {
+               int16_t *data=engine->render_cycle();
+               
+               int rest=samples_per_buffer-(buffer_pos+vtt_buffer_size);               
+               
+               if (rest>0) {
+                       memcpy(&target_buffer[buffer_pos], data, samples_per_buffer << 1);
+               } else {
+                       rest*=-1;
+                                       
+                       memcpy(&target_buffer[buffer_pos], data, (vtt_buffer_size-rest) << 1);
+                       memcpy(next_target_buffer, &data[vtt_buffer_size-rest], rest << 1);
+                       prefill=rest;
+               }
+               
+               buffer_pos+=vtt_buffer_size;
+       }
+       
+       buffer_pos=prefill;
+}
+
+/* Driver Specific Code follows.. */
+
 #ifdef USE_OSS
 
 int tX_audiodevice_oss :: open()
@@ -116,12 +166,8 @@ int tX_audiodevice_oss :: close()
        return 0;
 }
 
-tX_audiodevice_oss :: tX_audiodevice_oss()
-{
-       fd=0;
-       blocksize=0;
-       init();
-}
+tX_audiodevice_oss :: tX_audiodevice_oss() : tX_audiodevice(),
+fd(0), blocksize(0) {}
 
 double tX_audiodevice_oss :: get_latency()
 {
@@ -259,11 +305,8 @@ double tX_audiodevice_alsa :: get_latency()
 }
 
 
-tX_audiodevice_alsa :: tX_audiodevice_alsa()
-{
-       pcm_handle=NULL;        
-       init();
-}
+tX_audiodevice_alsa :: tX_audiodevice_alsa() : tX_audiodevice(),
+pcm_handle(NULL) {}
 
 void tX_audiodevice_alsa :: play(int16_t *buffer)
 {
index 1d5c29156f481802678a521f38cf4dd991e6ed38..b9efb8b2ede436d1624e5260c610f636cb1c50e6 100644 (file)
 #include <alsa/asoundlib.h>
 #endif
 
+class tX_engine;
+
 class tX_audiodevice
 {
        protected:
        int samples_per_buffer;
+       int16_t *sample_buffer[2];
+       int current_buffer;
+       int buffer_pos;
+       tX_engine *engine;
+       
        int sample_rate;
-       void init();
+       tX_audiodevice();
        
        public:
        virtual double get_latency()=0; /* call only valid *after* open() */
@@ -51,7 +58,10 @@ class tX_audiodevice
        
        virtual int open()=0;
        virtual int close()=0;
-               
+       
+       void fill_buffer(int16_t *target_buffer, int16_t *next_target_buffer);
+
+       virtual void start();   
        virtual void play(int16_t*)=0; /* play blocked */
 };
 
index c3f52fa4affd24e17e23a54afde102e427bb2fcf..b161c62bd2783d8a05f9cb0d285040dc46bffe58 100644 (file)
@@ -103,6 +103,7 @@ void apply_options(GtkWidget *dialog) {
 
        /* Misc */
        strcpy(globals.file_editor, gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog, "soundfile_editor"))));
+       strcpy(globals.lrdf_path, gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path"))));
        globals.prelis=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")))==TRUE);
 }
 
@@ -339,6 +340,7 @@ void init_tx_options(GtkWidget *dialog) {
 
        /* Misc */
        gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog, "soundfile_editor")), globals.file_editor);
+       gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path")), globals.lrdf_path);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")), globals.prelis);
 }
 
index f7e09712d17dc6b44b66dda07e75c785f0d9d271..e570fdf5828f513eab0c368e9793fbf0fd911721 100644 (file)
 #include <sys/time.h>
 #include <sys/resource.h>
 
-tX_engine *engine=NULL;
+tX_engine *tX_engine :: engine=NULL;
+
+tX_engine *tX_engine :: get_instance() {
+       if (!engine) {
+               engine=new tX_engine();
+       }
+       
+       return engine;
+}
 
 void tX_engine :: set_grab_request() {
        grab_request=true;
 }
 
-void tX_engine :: loop() {
+void tX_engine :: loop_og() {
        int16_t *temp=NULL;
        int result;
        
@@ -130,6 +138,71 @@ void tX_engine :: loop() {
        }
 }
 
+int16_t* tX_engine :: render_cycle() {
+       /* Checking whether to grab or not  */
+       if (grab_request!=grab_active) {
+               if (grab_request) {
+                       /* Activating grab... */
+                       int result=mouse->grab(); 
+                       if (result!=0) {
+                               tX_error("tX_engine::loop(): failed to grab mouse - error %i", result);
+                               grab_active=false;
+                               /* Reseting grab_request, too - doesn't help keeping it, does it ? ;) */
+                               grab_request=false;
+                               mouse->ungrab();
+                               grab_off();
+                       } else {
+                               grab_active=true;
+                       }
+               } else {
+                       /* Deactivating grab... */
+                       mouse->ungrab();
+                       grab_active=false;
+                       grab_off(); // for the mastergui this is...
+               }
+       }
+
+       /* Handling input events... */
+       if (grab_active) {
+               if (mouse->check_event()) {
+                       /* If we're here the user pressed ESC */
+                       grab_request=false;
+               }
+       }
+
+#ifdef USE_ALSA_MIDI_IN                        
+       if (midi->get_is_open()) midi->check_event();
+#endif                 
+       /* Forward the sequencer... */
+       sequencer.step();
+
+       /* Render the next block... */
+       int16_t *data=vtt_class::render_all_turntables();
+       
+       /* Record the audio if necessary... */
+       if (is_recording()) tape->eat(data);
+       
+       return  data;
+}
+
+void tX_engine :: loop() {
+       int16_t *temp=NULL;
+       int result;
+       
+       while (!thread_terminate) {
+               /* Waiting for the trigger */
+               pthread_mutex_lock(&start);
+               loop_is_active=true;
+               pthread_mutex_unlock(&start);
+
+               device->start(); // Hand flow control over to the device
+               
+               /* Stopping engine... */
+               loop_is_active=false;
+       }
+}
+
+
 void *engine_thread_entry(void *engine_void) {
        tX_engine *engine=(tX_engine*) engine_void;
        int result;
@@ -256,7 +329,6 @@ tX_engine_error tX_engine :: run() {
        }       
 
        vtt_class::set_sample_rate(device->get_sample_rate());
-       vtt_class::set_mix_buffer_size(device->get_buffersize()/2); //mixbuffer is mono
        
        if (recording_request) {
                if (tape->start_record(globals.record_filename, device->get_buffersize()*sizeof(int16_t), device->get_sample_rate())) {
index f7f8096df11804ab768aa907438730590ed36df9..052ac66c5eaf4c95919061f2088405d3027d62e8 100644 (file)
@@ -59,6 +59,8 @@ enum tX_engine_status {
 
 class tX_engine {
        private:
+       static tX_engine *engine;
+       
        pthread_t thread;
        pthread_mutex_t start;
        bool thread_terminate;
@@ -79,18 +81,21 @@ class tX_engine {
        tX_midiin *get_midi() { return midi; }
 #endif 
 
+       static tX_engine *get_instance();
        tX_engine();
        ~tX_engine();
        
        tX_engine_error run();
        void stop();
        void loop();
+       void loop_og(); 
+       
        void set_recording_request(bool recording);
        bool get_recording_request() { return recording_request; }
        bool is_recording() { return recording; }
+       int16_t* render_cycle();
        
        void set_grab_request();
+       bool is_stopped() { return stop_flag; }
 };
-
-extern tX_engine *engine;
 #endif
index ee852eab2d7ba268d6c9e389010ec16300546950..c34a71f8e158d6df7d250bde55dd22f9de487096 100644 (file)
@@ -106,6 +106,8 @@ create_tx_options (void)
   GtkWidget *soundfile_editor;
   GtkWidget *label26;
   GtkWidget *prelisten_enabled;
+  GtkWidget *label31;
+  GtkWidget *ladspa_rdf_path;
   GtkWidget *label3;
   GtkWidget *dialog_action_area1;
   GtkWidget *pref_cancel;
@@ -560,7 +562,7 @@ create_tx_options (void)
   gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 5), label2);
   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
 
-  table3 = gtk_table_new (2, 2, FALSE);
+  table3 = gtk_table_new (3, 2, FALSE);
   gtk_widget_show (table3);
   gtk_container_add (GTK_CONTAINER (notebook1), table3);
   gtk_container_set_border_width (GTK_CONTAINER (table3), 4);
@@ -584,7 +586,7 @@ create_tx_options (void)
 
   label26 = gtk_label_new ("\"Pre-Listen\" to soundfiles:");
   gtk_widget_show (label26);
-  gtk_table_attach (GTK_TABLE (table3), label26, 0, 1, 1, 2,
+  gtk_table_attach (GTK_TABLE (table3), label26, 0, 1, 2, 3,
                     (GtkAttachOptions) (GTK_FILL),
                     (GtkAttachOptions) (0), 0, 0);
   gtk_label_set_justify (GTK_LABEL (label26), GTK_JUSTIFY_LEFT);
@@ -592,11 +594,25 @@ create_tx_options (void)
 
   prelisten_enabled = gtk_check_button_new_with_mnemonic ("Enabled");
   gtk_widget_show (prelisten_enabled);
-  gtk_table_attach (GTK_TABLE (table3), prelisten_enabled, 1, 2, 1, 2,
+  gtk_table_attach (GTK_TABLE (table3), prelisten_enabled, 1, 2, 2, 3,
                     (GtkAttachOptions) (GTK_FILL),
                     (GtkAttachOptions) (0), 0, 0);
   gtk_tooltips_set_tip (tooltips, prelisten_enabled, "When enabled soundfiles will be playedback when selected in a file dialog (before loading them).", NULL);
 
+  label31 = gtk_label_new ("LADSPA RDF Path:");
+  gtk_widget_show (label31);
+  gtk_table_attach (GTK_TABLE (table3), label31, 0, 1, 1, 2,
+                    (GtkAttachOptions) (GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_label_set_justify (GTK_LABEL (label31), GTK_JUSTIFY_LEFT);
+  gtk_misc_set_alignment (GTK_MISC (label31), 0, 0.5);
+
+  ladspa_rdf_path = gtk_entry_new ();
+  gtk_widget_show (ladspa_rdf_path);
+  gtk_table_attach (GTK_TABLE (table3), ladspa_rdf_path, 1, 2, 1, 2,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+
   label3 = gtk_label_new ("Misc");
   gtk_widget_show (label3);
   gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 6), label3);
@@ -707,6 +723,8 @@ create_tx_options (void)
   GLADE_HOOKUP_OBJECT (tx_options, soundfile_editor, "soundfile_editor");
   GLADE_HOOKUP_OBJECT (tx_options, label26, "label26");
   GLADE_HOOKUP_OBJECT (tx_options, prelisten_enabled, "prelisten_enabled");
+  GLADE_HOOKUP_OBJECT (tx_options, label31, "label31");
+  GLADE_HOOKUP_OBJECT (tx_options, ladspa_rdf_path, "ladspa_rdf_path");
   GLADE_HOOKUP_OBJECT (tx_options, label3, "label3");
   GLADE_HOOKUP_OBJECT_NO_REF (tx_options, dialog_action_area1, "dialog_action_area1");
   GLADE_HOOKUP_OBJECT (tx_options, pref_cancel, "pref_cancel");
index 255bc4fc0b743b15a3c833729b827704ebcca618..8d702b9ef8c7df587c363fe90f3c7c7fd98ac091 100644 (file)
@@ -532,7 +532,7 @@ GtkSignalFunc audio_on(GtkWidget *w, void *d)
        {               
                sequencer_ready=0;
                mg_enable_critical_buttons(0);
-               res=engine->run();
+               res=tX_engine::get_instance()->run();
                sequencer_ready=1;
 
                if (res!=NO_ERROR)
@@ -564,11 +564,11 @@ GtkSignalFunc audio_on(GtkWidget *w, void *d)
        {               
                if (!sequencer_ready) return NULL;
                gtk_widget_set_sensitive(grab_button, 0);
-               engine->stop();
+               tX_engine::get_instance()->stop();
                stop_update=1;
                audioon=0;
-               if (engine->get_recording_request()) {
-                       engine->set_recording_request(false);
+               if (tX_engine::get_instance()->get_recording_request()) {
+                       tX_engine::get_instance()->set_recording_request(false);
                        rec_dont_care=1;
                        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(rec_menu_item), 0);
                        rec_dont_care=0;
@@ -598,7 +598,7 @@ void do_rec(GtkWidget *wid)
        if (strlen(buffer))
        {
                strcpy(globals.record_filename, buffer);                
-               engine->set_recording_request(true);
+               tX_engine::get_instance()->set_recording_request(true);
                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(rec_menu_item), 1);
        }
        
@@ -650,7 +650,7 @@ GtkSignalFunc tape_on(GtkWidget *w, void *d)
        }
        else
        {
-                       engine->set_recording_request(false);
+                       tX_engine::get_instance()->set_recording_request(false);
        }
        
        return NULL;
@@ -659,7 +659,7 @@ GtkSignalFunc tape_on(GtkWidget *w, void *d)
 void grab_on(GtkWidget *w, void *d)
 {
        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))) {
-               engine->set_grab_request();
+               tX_engine::get_instance()->set_grab_request();
        }
        grab_status=1;
 }
index 97a9d329a00f3fd380978ea37f6587bb2d3ce31c..394e1662241f17da5e1ac6ea1197a04090342bff 100644 (file)
@@ -203,11 +203,12 @@ tX_midiin::midi_binding_gui::midi_binding_gui ( GtkTreeModel* _model, tX_midiin*
        
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title (GTK_WINDOW (window), "Configure MIDI Bindings");
-       gtk_window_set_default_size(GTK_WINDOW(window), 400, 260);
+       gtk_window_set_default_size(GTK_WINDOW(window), 600, 260);
        
-       hbox1 = gtk_hbox_new (FALSE, 0);
+       hbox1 = gtk_hbox_new (FALSE, 2);
        gtk_widget_show (hbox1);
        gtk_container_add (GTK_CONTAINER (window), hbox1);
+       gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
        
        scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
        gtk_widget_show (scrolledwindow1);
@@ -240,7 +241,7 @@ tX_midiin::midi_binding_gui::midi_binding_gui ( GtkTreeModel* _model, tX_midiin*
        frame1 = gtk_frame_new (NULL);
        gtk_widget_show (frame1);
        gtk_box_pack_start (GTK_BOX (vbox1), frame1, TRUE, TRUE, 0);
-       gtk_container_set_border_width (GTK_CONTAINER (frame1), 1);
+       gtk_container_set_border_width (GTK_CONTAINER (frame1), 2);
        gtk_frame_set_label_align (GTK_FRAME (frame1), 0, 0);
        gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
        
index 40f3152f7118e4e4426602f3f68e7e52ebe141e2..c628eff30f69e05f635750adfbe8ad3c6798c910 100644 (file)
@@ -96,6 +96,7 @@ vtt_class * vtt_class::focused_vtt=NULL;
 f_prec vtt_class::mix_max_l=0;
 f_prec vtt_class::mix_max_r=0;
 f_prec vtt_class::vol_channel_adjust=1.0;
+int vtt_class::mix_buffer_size=0;
 
 #define GAIN_AUTO_ADJUST 0.8
 
@@ -869,6 +870,9 @@ int vtt_class :: set_mix_buffer_size(int no_samples)
        }
        
        if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
+       
+       mix_buffer_size=no_samples;
+       
        return(0);
 }
 
@@ -2004,4 +2008,8 @@ void vtt_class :: set_sample_rate(int samplerate) {
                }
                (*vtt)->recalc_pitch();
        }
+       
+       int no_samples=(int) (sr*0.001); // Forcing 1 ms blocksize
+       
+       set_mix_buffer_size(no_samples);        
 }
index f0a67a9fc06ebcc40a86d06c5ad3208eb6876648..3ce27d46144c1882741a718569ecdee22c0e6991 100644 (file)
@@ -89,6 +89,7 @@ class vtt_class
        static int master_triggered_at;
        static vtt_class * focused_vtt;
        static int solo_ctr;
+       static int mix_buffer_size;
        
        /* the gui */
        vtt_gui gui;
@@ -227,6 +228,8 @@ class vtt_class
        vtt_class(int);
        ~vtt_class();
        
+       static int get_mix_buffer_size() { return mix_buffer_size; }
+       
        /* Parameter setup methods */
        void set_name(char *);
        int set_output_buffer_size(int);
index d3c117b664e4d718560582d2f0e77460631024a5..8180720dea9ab9e0b86a85671e662d9212b81ea0 100644 (file)
@@ -393,7 +393,7 @@ void ec_enabled(GtkWidget *wid, vtt_class *vtt)
 #ifdef USE_ALSA_MIDI_IN
 void midi_mapping_clicked(GtkWidget *wid, vtt_class *vtt)
 {
-       engine->midi->configure_bindings(vtt);
+       tX_engine::get_instance()->midi->configure_bindings(vtt);
 }
 #endif
 
@@ -785,7 +785,7 @@ void build_vtt_gui(vtt_class *vtt)
        gui_set_tooltip(g->midi_mapping, "Determines what parameters should be bound to what MIDI events.");
        gtk_box_pack_start(GTK_BOX(tempbox), g->midi_mapping, WID_DYN);
        
-       if (!engine->get_midi()->get_is_open()) {
+       if (!tX_engine::get_instance()->get_midi()->get_is_open()) {
                gtk_widget_set_sensitive(g->midi_mapping, FALSE);
        }
 #endif
index 858da335f8d1acda7bfcc98a7899400d422bb942..821e94fae1f4c60c94a81987449fe3010d4d1fe8 100644 (file)
            <widget class="GtkTable" id="table3">
              <property name="border_width">4</property>
              <property name="visible">True</property>
-             <property name="n_rows">2</property>
+             <property name="n_rows">3</property>
              <property name="n_columns">2</property>
              <property name="homogeneous">False</property>
              <property name="row_spacing">2</property>
                <packing>
                  <property name="left_attach">0</property>
                  <property name="right_attach">1</property>
-                 <property name="top_attach">1</property>
-                 <property name="bottom_attach">2</property>
+                 <property name="top_attach">2</property>
+                 <property name="bottom_attach">3</property>
                  <property name="x_options">fill</property>
                  <property name="y_options"></property>
                </packing>
                <packing>
                  <property name="left_attach">1</property>
                  <property name="right_attach">2</property>
+                 <property name="top_attach">2</property>
+                 <property name="bottom_attach">3</property>
+                 <property name="x_options">fill</property>
+                 <property name="y_options"></property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkLabel" id="label31">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">LADSPA RDF Path:</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="left_attach">0</property>
+                 <property name="right_attach">1</property>
                  <property name="top_attach">1</property>
                  <property name="bottom_attach">2</property>
                  <property name="x_options">fill</property>
                  <property name="y_options"></property>
                </packing>
              </child>
+
+             <child>
+               <widget class="GtkEntry" id="ladspa_rdf_path">
+                 <property name="visible">True</property>
+                 <property name="can_focus">True</property>
+                 <property name="editable">True</property>
+                 <property name="visibility">True</property>
+                 <property name="max_length">0</property>
+                 <property name="text" translatable="yes"></property>
+                 <property name="has_frame">True</property>
+                 <property name="invisible_char" translatable="yes">*</property>
+                 <property name="activates_default">False</property>
+               </widget>
+               <packing>
+                 <property name="left_attach">1</property>
+                 <property name="right_attach">2</property>
+                 <property name="top_attach">1</property>
+                 <property name="bottom_attach">2</property>
+                 <property name="y_options"></property>
+               </packing>
+             </child>
            </widget>
            <packing>
              <property name="tab_expand">False</property>