From 17ab3548d7d6b9da1a141fc3e8b631cd16bacef9 Mon Sep 17 00:00:00 2001
From: John Melton - G0ORX/N6LYT <john.d.melton@googlemail.com>
Date: Mon, 19 Dec 2016 16:39:06 +0000
Subject: [PATCH] Fixed problem with linein gain not setting correctly.

---
 audio.c        |  2 +-
 audio_menu.c   |  2 ++
 configure.c    | 28 ++++++++++++++++
 gpio.c         |  8 +++--
 iambic.c       | 35 +++++++-------------
 iambic.h       | 18 +++++++++++
 main.c         | 16 +++++++---
 new_menu.c     | 15 +++++----
 new_protocol.c |  9 ++++--
 old_protocol.c |  2 +-
 radio.c        |  7 +++-
 radio.h        |  3 +-
 sliders.c      | 87 ++++++++++++++++++++++++++++++++++++++++++++------
 sliders.h      |  1 +
 14 files changed, 179 insertions(+), 54 deletions(-)

diff --git a/audio.c b/audio.c
index b46ab8a..0b3ae13 100644
--- a/audio.c
+++ b/audio.c
@@ -298,7 +298,7 @@ int audio_write(short left_sample,short right_sample) {
       if(snd_pcm_delay(playback_handle,&delay)==0) {
         if(delay>2048) {
           trim=delay-2048;
-fprintf(stderr,"audio delay=%ld trim=%ld\n",delay,trim);
+//fprintf(stderr,"audio delay=%ld trim=%ld\n",delay,trim);
         }
       }
 
diff --git a/audio_menu.c b/audio_menu.c
index 684bba2..2045be8 100644
--- a/audio_menu.c
+++ b/audio_menu.c
@@ -27,6 +27,7 @@
 #include "audio.h"
 #include "channel.h"
 #include "radio.h"
+#include "sliders.h"
 #include "wdsp.h"
 
 static GtkWidget *parent_window=NULL;
@@ -58,6 +59,7 @@ static void micboost_cb(GtkWidget *widget, gpointer data) {
 
 static void linein_cb(GtkWidget *widget, gpointer data) {
   mic_linein=mic_linein==1?0:1;
+  linein_changed();
 }
 
 static void local_audio_cb(GtkWidget *widget, gpointer data) {
diff --git a/configure.c b/configure.c
index ecc36ee..d33ce08 100644
--- a/configure.c
+++ b/configure.c
@@ -268,6 +268,32 @@ void configure_gpio(GtkWidget *parent) {
   gtk_widget_show(function);
   gtk_grid_attach(GTK_GRID(grid),function,2,10,1,1);
 
+  GtkWidget *cwl_label=gtk_label_new("CWL");
+  gtk_widget_show(cwl_label);
+  gtk_grid_attach(GTK_GRID(grid),cwl_label,0,11,1,1);
+
+  GtkWidget *cwl_gpio_label=gtk_label_new("GPIO:");
+  gtk_widget_show(cwl_gpio_label);
+  gtk_grid_attach(GTK_GRID(grid),cwl_gpio_label,1,11,1,1);
+
+  GtkWidget *cwl=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwl),CWL_BUTTON);
+  gtk_widget_show(cwl);
+  gtk_grid_attach(GTK_GRID(grid),cwl,2,11,1,1);
+
+  GtkWidget *cwr_label=gtk_label_new("CWR");
+  gtk_widget_show(cwr_label);
+  gtk_grid_attach(GTK_GRID(grid),cwr_label,0,12,1,1);
+
+  GtkWidget *cwr_gpio_label=gtk_label_new("GPIO:");
+  gtk_widget_show(cwr_gpio_label);
+  gtk_grid_attach(GTK_GRID(grid),cwr_gpio_label,1,12,1,1);
+
+  GtkWidget *cwr=gtk_spin_button_new_with_range (0.0,100.0,1.0);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON(cwr),CWR_BUTTON);
+  gtk_widget_show(cwr);
+  gtk_grid_attach(GTK_GRID(grid),cwr,2,12,1,1);
+
 
 
   gtk_container_add(GTK_CONTAINER(content),grid);
@@ -310,6 +336,8 @@ void configure_gpio(GtkWidget *parent) {
   MOX_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(mox));
   ENABLE_FUNCTION_BUTTON=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b_enable_function))?1:0;
   FUNCTION_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(function));
+  CWL_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwl));
+  CWR_BUTTON=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cwr));
 
   gtk_widget_destroy(dialog);
 
diff --git a/gpio.c b/gpio.c
index 63f426c..6dbce48 100644
--- a/gpio.c
+++ b/gpio.c
@@ -90,8 +90,8 @@ int FUNCTION_BUTTON=22;
 int ENABLE_LOCK_BUTTON=1;
 int ENABLE_CW_BUTTONS=1;
 // make sure to disable UART0 for next 2 gpios
-int CWL_BUTTON=15;
-int CWR_BUTTON=14;
+int CWL_BUTTON=9;
+int CWR_BUTTON=10;
 
 #ifdef sx1509
 /* Hardware Hookup:
@@ -727,12 +727,16 @@ fprintf(stderr,"encoder_init\n");
 #endif
 
   if(ENABLE_CW_BUTTONS) {
+    setup_button(CWL_BUTTON, cwAlert);
+    setup_button(CWR_BUTTON, cwAlert);
+/*
     gpioSetMode(CWL_BUTTON, PI_INPUT);
     gpioSetAlertFunc(CWL_BUTTON, cwAlert);
     gpioSetMode(CWR_BUTTON, PI_INPUT);
     gpioSetAlertFunc(CWR_BUTTON, cwAlert);
     gpioGlitchFilter(CWL_BUTTON, 5000);
     gpioGlitchFilter(CWR_BUTTON, 5000);
+*/
   }
  
 #endif
diff --git a/iambic.c b/iambic.c
index d8084a6..35ea9cb 100644
--- a/iambic.c
+++ b/iambic.c
@@ -89,6 +89,7 @@ static pthread_t keyer_thread_id;
 #define MAX_SAFE_STACK (8*1024)
 #define NSEC_PER_SEC   (1000000000)
 
+/*
 enum {
     CHECK = 0,
     PREDOT,
@@ -102,17 +103,18 @@ enum {
     LETTERSPACE,
     EXITLOOP
 };
+*/
 
 static int dot_memory = 0;
 static int dash_memory = 0;
-static int key_state = 0;
+int key_state = 0;
 static int kdelay = 0;
 static int dot_delay = 0;
 static int dash_delay = 0;
 static int kcwl = 0;
 static int kcwr = 0;
-static int *kdot;
-static int *kdash;
+int *kdot;
+int *kdash;
 static int running = 0;
 static sem_t cw_event;
 
@@ -157,8 +159,9 @@ void keyer_event(int gpio, int level) {
     else  // CWR_BUTTON
         kcwr = state;
 
-    if (state || cw_keyer_mode == KEYER_STRAIGHT)
+    if (state || cw_keyer_mode == KEYER_STRAIGHT) {
         sem_post(&cw_event);
+    }
 }
 
 void clear_memory() {
@@ -173,13 +176,15 @@ void set_keyer_out(int state) {
         if (state)
             if (SIDETONE_GPIO)
                 softToneWrite (SIDETONE_GPIO, cw_keyer_sidetone_frequency);
-            else
+            else {
                 beep_mute(1);
+            }
         else
             if (SIDETONE_GPIO)
                 softToneWrite (SIDETONE_GPIO, 0);
-            else
+            else  {
                 beep_mute(0);
+            }
     }
 }
 
@@ -376,26 +381,10 @@ int keyer_init() {
             running = 0;
     }
 
-    stack_prefault();
+    //stack_prefault();
 
-    fprintf(stderr,"keyer_init\n");
 
     if (wiringPiSetup () < 0) {
-        fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno));
-        return 1;
-    }
-
-    if (SIDETONE_GPIO)
-        softToneCreate(SIDETONE_GPIO);
-    else {
-        beep_init();
-        beep_vol(cw_keyer_sidetone_volume);
-    }
-
-    rc = sem_init(&cw_event, 0, 0);
-    rc |= pthread_create(&keyer_thread_id, NULL, keyer_thread, NULL);
-    running = 1;
-    if(rc < 0) {
         fprintf(stderr,"pthread_create for keyer_thread failed %d\n", rc);
         exit(-1);
     }
diff --git a/iambic.h b/iambic.h
index 3585fd6..f67fac4 100644
--- a/iambic.h
+++ b/iambic.h
@@ -1,10 +1,28 @@
 #ifndef _IAMBIC_H
 #define _IAMBIC_H
 
+enum {
+    CHECK = 0,
+    PREDOT,
+    PREDASH,
+    SENDDOT,
+    SENDDASH,
+    DOTDELAY,
+    DASHDELAY,
+    DOTHELD,
+    DASHHELD,
+    LETTERSPACE,
+    EXITLOOP
+};
+
 extern int cwl_state;
 extern int cwr_state;
 extern int keyer_out;
 
+extern int key_state;
+extern int *kdot;
+extern int *kdash;
+
 void keyer_event(int gpio, int level);
 void keyer_update();
 void keyer_close();
diff --git a/main.c b/main.c
index 858defd..53df2ed 100644
--- a/main.c
+++ b/main.c
@@ -65,19 +65,23 @@
 #include "psk_waterfall.h"
 #endif
 
-#define VFO_HEIGHT ((display_height/32)*4)
+#define DISPLAY_INCREMENT (display_height/32)
+#define VFO_HEIGHT (DISPLAY_INCREMENT*4)
+//#define VFO_HEIGHT (DISPLAY_INCREMENT*8)
 #define VFO_WIDTH ((display_width/32)*16)
 #define MENU_HEIGHT VFO_HEIGHT
+//#define MENU_HEIGHT (DISPLAY_INCREMENT*4)
 #define MENU_WIDTH ((display_width/32)*8)
 #define RIT_WIDTH ((MENU_WIDTH/3)*2)
 #define METER_HEIGHT VFO_HEIGHT
+//#define METER_HEIGHT (DISPLAY_INCREMENT*4)
 #define METER_WIDTH ((display_width/32)*8)
-#define PANADAPTER_HEIGHT ((display_height/32)*8)
-#define SLIDERS_HEIGHT ((display_height/32)*6)
-#define TOOLBAR_HEIGHT ((display_height/32)*2)
+#define PANADAPTER_HEIGHT (DISPLAY_INCREMENT*8)
+#define SLIDERS_HEIGHT (DISPLAY_INCREMENT*6)
+#define TOOLBAR_HEIGHT (DISPLAY_INCREMENT*2)
 #define WATERFALL_HEIGHT (display_height-(VFO_HEIGHT+PANADAPTER_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
 #ifdef PSK
-#define PSK_WATERFALL_HEIGHT ((display_height/32)*6)
+#define PSK_WATERFALL_HEIGHT (DISPLAY_INCREMENT*6)
 #define PSK_HEIGHT (display_height-(VFO_HEIGHT+PSK_WATERFALL_HEIGHT+SLIDERS_HEIGHT+TOOLBAR_HEIGHT))
 #endif
 
@@ -717,6 +721,8 @@ fprintf(stderr,"start: selected radio=%p device=%d\n",radio,radio->device);
 
   gtk_widget_show_all (window);
 
+  linein_changed();
+
   if(full_screen) {
     gtk_window_fullscreen(GTK_WINDOW(window));
   }
diff --git a/new_menu.c b/new_menu.c
index 1509f71..ff5fdf3 100644
--- a/new_menu.c
+++ b/new_menu.c
@@ -385,14 +385,14 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget,
     g_signal_connect (vox_b, "button-press-event", G_CALLBACK(vox_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),vox_b,2,3,1,1);
 
-    GtkWidget *diversity_b=gtk_button_new_with_label("Diversity");
-    g_signal_connect (diversity_b, "button-press-event", G_CALLBACK(diversity_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),diversity_b,3,3,1,1);
-
     GtkWidget *frequency_b=gtk_button_new_with_label("Frequency");
     g_signal_connect (frequency_b, "button-press-event", G_CALLBACK(freqent_cb), NULL);
-    gtk_grid_attach(GTK_GRID(grid),frequency_b,4,3,1,1);
-
+    gtk_grid_attach(GTK_GRID(grid),frequency_b,3,3,1,1);
+/*
+    GtkWidget *diversity_b=gtk_button_new_with_label("Diversity");
+    g_signal_connect (diversity_b, "button-press-event", G_CALLBACK(diversity_cb), NULL);
+    gtk_grid_attach(GTK_GRID(grid),diversity_b,4,3,1,1);
+*/
     GtkWidget *band_b=gtk_button_new_with_label("Band");
     g_signal_connect (band_b, "button-press-event", G_CALLBACK(band_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),band_b,0,4,1,1);
@@ -417,10 +417,11 @@ static gboolean new_menu_pressed_event_cb (GtkWidget *widget,
     g_signal_connect (agc_b, "button-press-event", G_CALLBACK(agc_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),agc_b,5,4,1,1);
 
+/*
     GtkWidget *test_b=gtk_button_new_with_label("Test");
     g_signal_connect (test_b, "button-press-event", G_CALLBACK(test_cb), NULL);
     gtk_grid_attach(GTK_GRID(grid),test_b,0,5,1,1);
-
+*/
     gtk_container_add(GTK_CONTAINER(content),grid);
 
     gtk_widget_show_all(dialog);
diff --git a/new_protocol.c b/new_protocol.c
index d689d79..75972ef 100644
--- a/new_protocol.c
+++ b/new_protocol.c
@@ -328,6 +328,10 @@ static void new_protocol_high_priority(int run) {
         // set the ptt if we're not in breakin mode and mox is on
         if(cw_breakin == 0 && getMox()) buffer[4]|=0x02;
         buffer[5]|=(keyer_out) ? 0x01 : 0;
+        //buffer[5]|=(*kdot) ? 0x02 : 0;
+        //buffer[5]|=(*kdash) ? 0x04 : 0;
+        buffer[5]|=(key_state==SENDDOT) ? 0x02 : 0;
+        buffer[5]|=(key_state==SENDDASH) ? 0x04 : 0;
       }
 #endif
     } else {
@@ -599,9 +603,8 @@ static void new_protocol_transmit_specific() {
       buffer[50]|=0x08;
     }
 
-    // 0..30
-    int g=(int)(30.0*mic_gain);
-    buffer[51]=g&0xFF; // Line in gain
+    // 0..31
+    buffer[51]=linein_gain;
 
     if(sendto(data_socket,buffer,sizeof(buffer),0,(struct sockaddr*)&transmitter_addr,transmitter_addr_length)<0) {
         fprintf(stderr,"sendto socket failed for tx specific\n");
diff --git a/old_protocol.c b/old_protocol.c
index 0d15e86..58cbd41 100644
--- a/old_protocol.c
+++ b/old_protocol.c
@@ -1005,7 +1005,7 @@ void ozy_send_buffer() {
       if(mic_ptt_tip_bias_ring) {
         output_buffer[C1]|=0x10;
       }
-      output_buffer[C2]=0x00;
+      output_buffer[C2]=linein_gain;
       output_buffer[C3]=0x00;
 
       if(radio->device==DEVICE_HERMES || radio->device==DEVICE_ANGELIA || radio->device==DEVICE_ORION) {
diff --git a/radio.c b/radio.c
index 30717ab..65f0fdd 100644
--- a/radio.c
+++ b/radio.c
@@ -100,6 +100,7 @@ int rx_random=0;
 int rx_preamp=0;
 
 int mic_linein=0;
+int linein_gain=16; // 0..31
 int mic_boost=0;
 int mic_bias_enabled=0;
 int mic_ptt_enabled=0;
@@ -567,7 +568,9 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     value=getProperty("mic_boost");
     if(value) mic_boost=atof(value);
     value=getProperty("mic_linein");
-    if(value) mic_linein=atof(value);
+    if(value) mic_linein=atoi(value);
+    value=getProperty("linein_gain");
+    if(value) linein_gain=atoi(value);
     value=getProperty("mic_ptt_enabled");
     if(value) mic_ptt_enabled=atof(value);
     value=getProperty("mic_bias_enabled");
@@ -767,6 +770,8 @@ void radioSaveState() {
     setProperty("mic_boost",value);
     sprintf(value,"%d",mic_linein);
     setProperty("mic_linein",value);
+    sprintf(value,"%d",linein_gain);
+    setProperty("linein_gain",value);
     sprintf(value,"%d",mic_ptt_enabled);
     setProperty("mic_ptt_enabled",value);
     sprintf(value,"%d",mic_bias_enabled);
diff --git a/radio.h b/radio.h
index 7cd4bda..9008961 100644
--- a/radio.h
+++ b/radio.h
@@ -52,7 +52,7 @@ extern char property_path[];
 #define APOLLO 2
 
 // soecify how many receivers (only 1 or 2 for now)
-#define RECEIVERS 2
+#define RECEIVERS 1
 
 /*
 #define PA_DISABLED 0
@@ -131,6 +131,7 @@ extern int nr2_npe_method;
 extern int nr2_ae;
 
 extern int mic_linein;
+extern int linein_gain;
 extern int mic_boost;
 extern int mic_bias_enabled;
 extern int mic_ptt_enabled;
diff --git a/sliders.c b/sliders.c
index 9361387..d33cf94 100644
--- a/sliders.c
+++ b/sliders.c
@@ -48,12 +48,11 @@ static GtkWidget *sliders;
 #define NONE 0
 #define AF_GAIN 1
 #define MIC_GAIN 2
-#define AGC_GAIN 3
-#define DRIVE 4
-#define TUNE_DRIVE 5
-#define ATTENUATION 6
-
-//#define MIC_GAIN_FUDGE 25.0
+#define LINEIN_GAIN 3
+#define AGC_GAIN 4
+#define DRIVE 5
+#define TUNE_DRIVE 6
+#define ATTENUATION 7
 
 static gint scale_timer;
 static int scale_status=NONE;
@@ -66,6 +65,8 @@ static GtkWidget *attenuation_label;
 static GtkWidget *attenuation_scale;
 static GtkWidget *mic_gain_label;
 static GtkWidget *mic_gain_scale;
+static GtkWidget *linein_gain_label;
+static GtkWidget *linein_gain_scale;
 static GtkWidget *drive_label;
 static GtkWidget *drive_scale;
 static GtkWidget *tune_label;
@@ -75,6 +76,22 @@ static GtkWidget *dummy_label;
 static GdkRGBA white;
 static GdkRGBA gray;
 
+void linein_changed() {
+  if(display_sliders) {
+    if(mic_linein) {
+      gtk_widget_hide(mic_gain_label);
+      gtk_widget_hide(mic_gain_scale);
+      gtk_widget_show(linein_gain_label);
+      gtk_widget_show(linein_gain_scale);
+    } else {
+      gtk_widget_hide(linein_gain_label);
+      gtk_widget_hide(linein_gain_scale);
+      gtk_widget_show(mic_gain_label);
+      gtk_widget_show(mic_gain_scale);
+    }
+  }
+}
+
 int scale_timeout_cb(gpointer data) {
   gtk_widget_destroy(scale_dialog);
   scale_status=NONE;
@@ -228,7 +245,7 @@ void set_mic_gain(double value) {
     }
     if(scale_status==NONE) {
       scale_status=MIC_GAIN;
-      scale_dialog=gtk_dialog_new_with_buttons(mic_linein?"Linein Gain (dB)":"Mic Gain (dB)",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      scale_dialog=gtk_dialog_new_with_buttons("Mic Gain (dB)",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
       GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
       mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-10.0, 50.0, 1.00);
       gtk_widget_set_size_request (mic_gain_scale, 400, 30);
@@ -253,6 +270,49 @@ int update_mic_gain(void *data) {
   return 0;
 }
 
+static void lineingain_value_changed_cb(GtkWidget *widget, gpointer data) {
+    linein_gain=(int)gtk_range_get_value(GTK_RANGE(widget));
+}
+
+void set_linein_gain(int value) {
+  linein_gain=value;
+  if(display_sliders) {
+    gtk_range_set_value (GTK_RANGE(linein_gain_scale),linein_gain);
+  } else {
+    if(scale_status!=LINEIN_GAIN) {
+      if(scale_status!=NONE) {
+        g_source_remove(scale_timer);
+        gtk_widget_destroy(scale_dialog);
+        scale_status=NONE;
+      }
+    }
+    if(scale_status==NONE) {
+      scale_status=LINEIN_GAIN;
+      scale_dialog=gtk_dialog_new_with_buttons("Linein Gain",GTK_WINDOW(parent_window),GTK_DIALOG_DESTROY_WITH_PARENT,NULL,NULL);
+      GtkWidget *content=gtk_dialog_get_content_area(GTK_DIALOG(scale_dialog));
+      linein_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.00);
+      gtk_widget_set_size_request (linein_gain_scale, 400, 30);
+      gtk_range_set_value (GTK_RANGE(linein_gain_scale),linein_gain);
+      gtk_widget_show(linein_gain_scale);
+      gtk_container_add(GTK_CONTAINER(content),linein_gain_scale);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+      //gtk_widget_show_all(scale_dialog);
+      int result=gtk_dialog_run(GTK_DIALOG(scale_dialog));
+    } else {
+      g_source_remove(scale_timer);
+      gtk_range_set_value (GTK_RANGE(linein_gain_scale),linein_gain);
+      scale_timer=g_timeout_add(2000,scale_timeout_cb,NULL);
+    }
+
+  }
+}
+
+int update_linein_gain(void *data) {
+  set_linein_gain(*(int*)data);
+  free(data);
+  return 0;
+}
+
 void set_drive(double value) {
   setDrive(value);
   if(display_sliders) {
@@ -378,17 +438,24 @@ GtkWidget *sliders_init(int my_width, int my_height, GtkWidget* parent) {
 
 
 
-  mic_gain_label=gtk_label_new(mic_linein?"Linein (dB):":"Mic (dB):");
+  mic_gain_label=gtk_label_new("Mic (dB):");
   //gtk_widget_override_font(mic_gain_label, pango_font_description_from_string("Arial 16"));
-  gtk_widget_show(mic_gain_label);
   gtk_grid_attach(GTK_GRID(sliders),mic_gain_label,0,1,1,1);
 
   mic_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,-10.0, 50.0, 1.0);
   gtk_range_set_value (GTK_RANGE(mic_gain_scale),mic_gain);
-  gtk_widget_show(mic_gain_scale);
   gtk_grid_attach(GTK_GRID(sliders),mic_gain_scale,1,1,2,1);
   g_signal_connect(G_OBJECT(mic_gain_scale),"value_changed",G_CALLBACK(micgain_value_changed_cb),NULL);
 
+  linein_gain_label=gtk_label_new("Linein:");
+  gtk_grid_attach(GTK_GRID(sliders),linein_gain_label,0,1,1,1);
+
+  linein_gain_scale=gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,0.0, 31.0, 1.0);
+  gtk_range_set_value (GTK_RANGE(linein_gain_scale),linein_gain);
+  gtk_widget_show(linein_gain_scale);
+  gtk_grid_attach(GTK_GRID(sliders),linein_gain_scale,1,1,2,1);
+  g_signal_connect(G_OBJECT(linein_gain_scale),"value_changed",G_CALLBACK(lineingain_value_changed_cb),NULL);
+
   drive_label=gtk_label_new("Drive:");
   //gtk_widget_override_font(drive_label, pango_font_description_from_string("Arial 16"));
   gtk_widget_show(drive_label);
diff --git a/sliders.h b/sliders.h
index 8225e13..1601753 100644
--- a/sliders.h
+++ b/sliders.h
@@ -20,6 +20,7 @@
 #ifndef _SLIDERS_H
 #define _SLIDERS_H
 
+extern void linein_changed();
 extern int update_agc_gain(void *);
 extern int update_af_gain(void *);
 extern int update_mic_gain(void *);
-- 
2.45.2