]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Port to MacOS, Compiler warnings removed, thus found many errors.
authorc vw <dl1ycf@darc.de>
Fri, 8 Jun 2018 10:13:55 +0000 (12:13 +0200)
committerc vw <dl1ycf@darc.de>
Fri, 8 Jun 2018 10:13:55 +0000 (12:13 +0200)
Includes two fixes for STEMlab/HAMlab.

43 files changed:
MacOS/Info.plist [new file with mode: 0644]
MacOS/PkgInfo [new file with mode: 0644]
MacOS/hpsdr.icns [new file with mode: 0644]
MacOS/hpsdr.png [new file with mode: 0755]
MacOS/pihpsdr.sh [new file with mode: 0755]
Makefile
README.MacOS [new file with mode: 0644]
agc_menu.c
audio.c
audio_waterfall.c
band_menu.c
bandstack_menu.c
dsp_menu.c
equalizer_menu.c
error_handler.c
ext.c
filter_menu.c
freqent_menu.c
iambic.c
main.c
mode_menu.c
new_discovery.c
new_protocol.c
new_protocol.h
new_protocol_programmer.c
old_discovery.c
old_protocol.c
portaudio.c [new file with mode: 0644]
radio.c
receiver.c
receiver.h
rigctl.c
rx_menu.c
stemlab_discovery.c
step_menu.c
store_menu.c
transmitter.c
tx_menu.c
tx_panadapter.c
vfo.c
vfo_menu.c
vox_menu.c
waterfall.c

diff --git a/MacOS/Info.plist b/MacOS/Info.plist
new file mode 100644 (file)
index 0000000..9bca968
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>CFBundleIdentifier</key>
+       <string>piHPSDR</string>
+       <key>CFBundleExecutable</key>
+       <string>pihpsdr</string>
+       <key>CFBundleIconFile</key>
+       <string>hpsdr.icns</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+        <key>CFBundleSignature</key>
+       <string>BNDL</string>
+</dict>
+</plist>
diff --git a/MacOS/PkgInfo b/MacOS/PkgInfo
new file mode 100644 (file)
index 0000000..610abe0
--- /dev/null
@@ -0,0 +1 @@
+APPLpihp
diff --git a/MacOS/hpsdr.icns b/MacOS/hpsdr.icns
new file mode 100644 (file)
index 0000000..4d1f6a8
Binary files /dev/null and b/MacOS/hpsdr.icns differ
diff --git a/MacOS/hpsdr.png b/MacOS/hpsdr.png
new file mode 100755 (executable)
index 0000000..ea96fd7
Binary files /dev/null and b/MacOS/hpsdr.png differ
diff --git a/MacOS/pihpsdr.sh b/MacOS/pihpsdr.sh
new file mode 100755 (executable)
index 0000000..314c755
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+#
+# Launch the exe file from a shell.
+# This is the only way to make a GTK app bundle
+# It still relies on a working GTK installation
+#
+# A full-fledged wrapper here would set dozens of
+# environment variables.
+#
+this=`dirname $0` 
+cd $this/../Resources
+
+exec $this/pihpsdr-bin
index a27c99e1dd6e5a7dbf14e061c58d906066615998..0b89ea6fe7bb428fabf162b67f0536883f51b750 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,15 @@
 GIT_DATE := $(firstword $(shell git --no-pager show --date=short --format="%ai" --name-only))
 GIT_VERSION := $(shell git describe --abbrev=0 --tags)
 
+#DL1YCF: this uses PortAudio rather than ALSA
+PORTAUDIO_INCLUDE=PORTAUDIO
+
+#DL1YCF: un-commment this line for activate work-around some RedPitaty HPSDR bugs
+STEMLAB_FIX_OPTION=-DSTEMLAB_FIX
+
+#DL1YCF: un-commment if you need librt (probably always, except on MacOS)
+#LIBRT= -lrt
+
 # uncomment the line below to include GPIO
 #GPIO_INCLUDE=GPIO
 
@@ -27,18 +36,31 @@ GIT_VERSION := $(shell git describe --abbrev=0 --tags)
 # uncomment the line to below include support local CW keyer
 #LOCALCW_INCLUDE=LOCALCW
 
-# uncomment the line below to include support for STEMlab discovery
+# uncomment the line below to include support for STEMlab discovery (does not work on MacOS)
 #STEMLAB_DISCOVERY=STEMLAB_DISCOVERY
 
+# uncomment the line below to include support for stripped-down STEMlab discovery that works on MacOS
+STEMLAB_DISCOVERY=STEMLAB_DISCOVERY_MAC
+
 #uncomment the line below for the platform being compiled on
-UNAME_N=raspberrypi
+UNAME_N=MacOS
+#UNAME_N=raspberrypi
 #UNAME_N=odroid
 #UNAME_N=up
 #UNAME_N=pine64
 #UNAME_N=jetsen
 
 CC=gcc
+
+ifeq ($(UNAME_N),MacOS)
+#
+# This is only necessary for "make app", since the "patched"
+# library names are longer
+#
+LINK=gcc -headerpad_max_install_names
+else
 LINK=gcc
+endif
 
 # uncomment the line below for various debug facilities
 #DEBUG_OPTION=-D DEBUG
@@ -164,6 +186,17 @@ ifeq ($(I2C_INCLUDE),I2C)
   I2C_OBJS=i2c.o
 endif
 
+#
+# STEMLAB_DISCOVERY_MAC depends on curl but not on avahi
+#
+ifeq ($(STEMLAB_DISCOVERY), STEMLAB_DISCOVERY_MAC)
+STEMLAB_OPTIONS=-D STEMLAB_DISCOVERY `pkg-config --cflags libcurl`
+STEMLAB_LIBS=`pkg-config --libs libcurl`
+STEMLAB_SOURCES=stemlab_discovery.c
+STEMLAB_HEADERS=stemlab_discovery.h
+STEMLAB_OBJS=stemlab_discovery.o
+endif
+
 ifeq ($(STEMLAB_DISCOVERY), STEMLAB_DISCOVERY)
 STEMLAB_OPTIONS=-D STEMLAB_DISCOVERY \
   `pkg-config --cflags avahi-gobject` \
@@ -177,12 +210,23 @@ endif
 GTKINCLUDES=`pkg-config --cflags gtk+-3.0`
 GTKLIBS=`pkg-config --libs gtk+-3.0`
 
+ifeq ($(PORTAUDIO_INCLUDE), PORTAUDIO)
+PORTAUDIO_OPTIONS=-DPORTAUDIO
+AUDIO_LIBS=-lportaudio
+else
 AUDIO_LIBS=-lasound
 #AUDIO_LIBS=-lsoundio
+endif
+
+OPTIONS=-g -Wno-deprecated-declarations $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(RADIOBERRY_OPTIONS) \
+       $(USBOZY_OPTIONS)  $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) \
+       $(LOCALCW_OPTIONS) $(PSK_OPTIONS)  $(STEMLAB_OPTIONS) $(STEMLAB_FIX_OPTION) \
+       $(PORTAUDIO_OPTIONS) \
+       -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
 
-OPTIONS=-g -Wno-deprecated-declarations $(PURESIGNAL_OPTIONS) $(REMOTE_OPTIONS) $(USBOZY_OPTIONS) $(I2C_OPTIONS) $(GPIO_OPTIONS) $(LIMESDR_OPTIONS) $(FREEDV_OPTIONS) $(LOCALCW_OPTIONS) $(RADIOBERRY_OPTIONS) $(PSK_OPTIONS) $(STEMLAB_OPTIONS) -D GIT_DATE='"$(GIT_DATE)"' -D GIT_VERSION='"$(GIT_VERSION)"' $(DEBUG_OPTION) -O3
+LIBS= $(LIBRT) -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) \
+       $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS)
 
-LIBS=-lrt -lm -lwdsp -lpthread $(AUDIO_LIBS) $(USBOZY_LIBS) $(PSKLIBS) $(GTKLIBS) $(GPIO_LIBS) $(SOAPYSDRLIBS) $(FREEDVLIBS) $(STEMLAB_LIBS)
 INCLUDES=$(GTKINCLUDES)
 
 COMPILE=$(CC) $(OPTIONS) $(INCLUDES)
@@ -213,6 +257,7 @@ dsp_menu.c \
 pa_menu.c \
 cw_menu.c \
 oc_menu.c \
+portaudio.c \
 xvtr_menu.c \
 equalizer_menu.c \
 step_menu.c \
@@ -398,10 +443,11 @@ store_menu.o \
 memory.o \
 led.o \
 ext.o \
-error_handler.o
+error_handler.o \
+portaudio.o
 
 $(PROGRAM):  $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) $(STEMLAB_OBJS)
-       $(LINK) -o $(PROGRAM) $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(LIBS) $(PURESIGNAL_OBJS) $(STEMLAB_OBJS)
+       $(LINK) -o $(PROGRAM) $(OBJS) $(REMOTE_OBJS) $(USBOZY_OBJS) $(I2C_OBJS) $(GPIO_OBJS) $(LIMESDR_OBJS) $(FREEDV_OBJS) $(LOCALCW_OBJS) $(PSK_OBJS) $(PURESIGNAL_OBJS) $(STEMLAB_OBJS) $(LIBS)
 
 all: prebuild  $(PROGRAM) $(HEADERS) $(REMOTE_HEADERS) $(USBOZY_HEADERS) $(LIMESDR_HEADERS) $(FREEDV_HEADERS) $(LOCALCW_HEADERS) $(I2C_HEADERS) $(GPIO_HEADERS) $(PSK_HEADERS) $(PURESIGNAL_HEADERS) $(STEMLAB_HEADERS) $(SOURCES) $(REMOTE_SOURCES) $(USBOZY_SOURCES) $(LIMESDR_SOURCES) $(FREEDV_SOURCES) $(I2C_SOURCES) $(GPIO_SOURCES) $(PSK_SOURCES) $(PURESIGNAL_SOURCES) $(STEMLAB_SOURCES)
 
@@ -411,6 +457,7 @@ prebuild:
 clean:
        -rm -f *.o
        -rm -f $(PROGRAM)
+       -rm -rf $(PROGRAM).app
 
 install: $(PROGRAM)
        cp $(PROGRAM) /usr/local/bin
@@ -420,3 +467,45 @@ release: $(PROGRAM)
        cd release; tar cvf pihpsdr.tar pihpsdr
        cd release; tar cvf pihpsdr-$(GIT_VERSION).tar pihpsdr
 
+#############################################################################
+#
+# This is for MacOS "app" creation ONLY
+#
+# Note: Note that we need a wrapper script to start the program, and
+#       that it requires a working GTK installation on the Mac.
+#       The program will not work if the
+#       libgtk, libgdk, libglib, libgobj, libgio libraries
+#       are copied to the Frameworks dir and "activated", because
+#       this stuff depends on tons of other files in /usr/local.
+#
+#       We bundle the "app" with the other libraries such as WDSP,
+#       portaudio, fftw etc. such that the "app" runs on Macs which
+#       do not have them. But it is *very* hard to do this with GTK.
+#
+#       ATTENTION
+#       =========
+#       Upon starting a freshly built application in an "app" bundle,
+#       it will do the FFT calculations required for wdspWisdom, since
+#       this is then stored *within* the app bundle.
+#
+#############################################################################
+app:  pihpsdr
+       @rm -rf pihpsdr.app
+       @mkdir -p pihpsdr.app/Contents/MacOS
+       @mkdir -p pihpsdr.app/Contents/Frameworks
+       @mkdir -p pihpsdr.app/Contents/Resources
+       @cp pihpsdr pihpsdr.app/Contents/MacOS/pihpsdr-bin
+       @cp MacOS/PkgInfo pihpsdr.app/Contents
+       @cp MacOS/Info.plist pihpsdr.app/Contents
+       @cp MacOS/hpsdr.icns pihpsdr.app/Contents/Resources/hpsdr.icns
+       @cp MacOS/pihpsdr.sh pihpsdr.app/Contents/MacOS/pihpsdr
+       @cp MacOS/hpsdr.png pihpsdr.app/Contents/Resources
+       @for lib in `otool -L pihpsdr.app/Contents/MacOS/pihpsdr-bin | grep dylib | sed -e "s/ (.*//" | grep -Ev "/(usr/lib|System)" | grep -Ev /libg `; do \
+         libfn="`basename $$lib`"; \
+         cp "$$lib" "pihpsdr.app/Contents/Frameworks/$$libfn"; \
+         chmod u+w "pihpsdr.app/Contents/Frameworks/$$libfn"; \
+         install_name_tool -id "@executable_path/../Frameworks/$libfn" "pihpsdr.app/Contents/Frameworks/$$libfn"; \
+         install_name_tool -change "$$lib" "@executable_path/../Frameworks/$$libfn" pihpsdr.app/Contents/MacOS/pihpsdr-bin; \
+       done
+#############################################################################
+
diff --git a/README.MacOS b/README.MacOS
new file mode 100644 (file)
index 0000000..a43b6a6
--- /dev/null
@@ -0,0 +1,141 @@
+===============================================================
+=                                                             =
+= piHPSDR on the Macintosh.                                   =
+=                                                             =
+= Port done by DL1YCF Christoph van Wullen.                   =
+=                                                             =
+===============================================================
+
+
+
+============================
+NOTES ON CHANGES IN THE CODE
+============================
+
+To make piHPSDR work on MacOS, I had to do two major things:
+
+a) Semaphores: MacOS does not have sem_t variables, only
+   sem_t pointers that must not be dereferences. Therefore
+   it has no working sem_init.
+   On MacOS one must use sem_open instead and use sem_t
+   pointers instead of sem_t variable throughout. This is
+   not recommended for LINUX, since named semaphores stay
+   alive even when the program terminates (on MacOS, all
+   semaphores are automatically destroyed). Therefore
+   *every* declaration of sem_t variable and *every*
+   call to semaphore functions had to be modified. Everything
+   is coded as
+
+#ifdef __APPLE__
+  use sem_t pointers
+#else
+  usem_t variables
+#endif
+
+   NOTE this change also applies to WDSP.
+
+b) Audio: MacOS does not have ALSA, therefore an additional
+   file portaudio.c is provided that is a functional duplicate
+   of audio.c. The whole file audio.c is not "protected with
+
+#ifndef PORTAUDIO
+everything in audio.c
+#endif
+
+  and the new file portaudio.c consequently reads
+
+#ifdef PORTAUDIO
+everything in portaudio.c
+#endif
+
+  such that one can link and compile both files. As an additional benefit,
+  the PortAudio module also offeres a two-tone generator as TX "mic" input.
+
+c) Only relevant for STEMLAB/HAMLAB: the "special" code that starts the
+   HPSDR application on the RedPitaya board via a browser interface relies
+   on AVAHI to detect the RedPitaya board. This does not work on MacOS
+   since we do not have AVAHI. However, libcurl is available on MacOS.
+   Therefore I provide a stripped-down version in the file stemlab_discovery.c
+   which assumes that the RedPitaya board is accessible by a fixed 
+   IP address. This address is read from $HOME/.rp.inet and set to 192.168.1.3
+   if this file could not be read.
+   If your STEMlab/HAMlab is then there, the list of applications is obtained
+   and the HPSDR application with highest priority is started, the priority
+   defined through the following list (first line = highest priority)
+
+   hamlab_sdr_transceiver_hpsdr
+   stemlab_sdr_transceiver_hpsdr
+   sdr_transceiver_hpsdr
+   sdr_receiver_hpsdr
+
+=============
+PREREQUISITES
+=============
+
+Since Audio and GUI are OpenSource and not Apple-specific, one needs some
+third-party libraries to link the program. Most recommended is to use
+"homebrew". You will need portaudio and gtk+3 for piHPSDR, and
+fftw3 for wdsp (which you have to compile separately). Note that packages
+such as gtk+3 depend on other packages, but these are automatically installed
+by homebrew.  The Makefile itself relies on pkg-config to determine the
+compile and link flags for certain external software.
+
+Of course, you need the Xcode command line tools (make, gcc, and friends).
+
+Before you compile piHPSDR, you need to compile wdsp. Using the Mac-Makefile
+there, "make install" will put libwdsp.dylib in /usr/local/lib. This is needed
+by piHPSDR.
+
+===================
+COMPILE and INSTALL
+===================
+
+
+That's easy. Just adjust the Makefile according to the instructions found there
+and type "make". In my case (I have a HAMLAB RedPitaya-based SDR box), I need
+the following options in the Makefile (and have all others commented out):
+
+PORTAUDIO_INCLUDE=PORTAUDIO
+STEMLAB_FIX_OPTION=-DSTEMLAB_FIX
+STEMLAB_DISCOVERY=STEMLAB_DISCOVERY_MAC
+UNAME_N=MacOS
+
+The first one activates the PortAudio code and disables the Linux ALSA
+code, the second option activates some work-arounds around some RedPitaya
+HPSDR application bugs (this is also required if you are NOT using MacOS),
+and the third option activates code to start the HPSDR program on a RedPitaya
+before the actual discovery stuff takes place.
+
+Note: never un-comment the lines containing LIBRT, GPI_INCLUDE, I2C_INCLUDE,
+SX1509_INCLUDE, or LOCALCW_INCLUDE. This software/hardware is not present on a Mac.
+
+As a result of "make", you get an executable file "pihpsdr" which you
+can start from the terminal. With "make app" you can make a click-able
+MacOS application bundle. However note that this bundle is not self-contained:
+it needs a working gtk+3 environment. To put all this into an app bundle
+would create an app file hundreds of MByte long: you need all those pixbuf
+loaders etc. etc. etc. installed.
+
+What we do is to include portaudio, WDSP, fftw3 and some other libs into the bundle.
+
+
+===========================
+piHPSDR and wsjtx or fldigi
+===========================
+
+a) CAT control: use hamlib, and choose "OpenHPSDR piHPSDR" radio model and
+   e.g. port number 19090.  Then, activate rigctl in the piHPSDR menu, choosing
+   the same port number there.
+
+b) Audio: here you need the "SoundFlower" free-software program for MacOS, that
+   provides virtual audio cables. I have stripped down this somewhat, it now provides
+   two stero devices (named VAC A and VAC B) and has less overhead, since audio data
+   is no longer processed (no volume control) but simply moved: after all, this is what
+   a "cable" is supposed to do.
+   
+   For example, you can Choose "VAC A" as the RX output device and "VAC B" as the
+   TX input (mic) device in piHPSDR, and choose "VAC B" as the output device and "VAC A"
+   as the input device in fldigi or wsjt-x.
+   The modified version of SoundFlower is available on my github account, github.com/dl1ycf,
+   with the name MacOSVirtualAudioCable.
+   
index f41a5a314165daa5e9b219bf76e3bea248308cf8..3c9262d77d6dbc6060fa34614da5d7b5df26fd32 100644 (file)
@@ -60,6 +60,10 @@ static gboolean agc_select_cb (GtkWidget *widget, gpointer        data) {
   //wdsp_set_agc(CHANNEL_RX0, agc);
   set_agc(active_receiver, active_receiver->agc);
   vfo_update();
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void agc_menu(GtkWidget *parent) {
diff --git a/audio.c b/audio.c
index 923685aa968bf54cedd439073e8d97235610d20b..f6a7439221cdc2162150a2b109e3c3c57bb8f8b3 100644 (file)
--- a/audio.c
+++ b/audio.c
 *
 */
 
+//
+// DL1YCF: If PortAudio is used instead of ALSO (e.g. on MacOS),
+//         this file is not used (and replaced by portaudio.c).
+
+#ifndef PORTAUDIO 
 
 #include <gtk/gtk.h>
 
@@ -527,4 +532,5 @@ fprintf(stderr,"output_device: %s\n",device_id);
     n++;
   }
   snd_device_name_free_hint(hints);
-}
\ No newline at end of file
+}
+#endif
index 48ed0b9c754e38538e15e86077d01e33d331cb82..cbf606f7d220790ebfa91e90e597d7fa79ac056b 100644 (file)
@@ -78,7 +78,8 @@ waterfall_configure_event_cb (GtkWidget         *widget,
   int height=gtk_widget_get_allocated_height (widget);
 fprintf(stderr,"audio: waterfall_configure_event: width=%d height=%d\n",width,height);
   pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
-  char *pixels = gdk_pixbuf_get_pixels (pixbuf);
+  // DL1YCF changed to uchar *
+  unsigned char *pixels = gdk_pixbuf_get_pixels (pixbuf);
 
   memset(pixels, 0, width*height*3);
 
@@ -135,7 +136,8 @@ void audio_waterfall_update() {
   int i;
 
   if(pixbuf) {
-    char *pixels = gdk_pixbuf_get_pixels (pixbuf);
+    // DL1YCF changed to uchar *
+    unsigned char *pixels = gdk_pixbuf_get_pixels (pixbuf);
 
     int width=gdk_pixbuf_get_width(pixbuf);
     int height=gdk_pixbuf_get_height(pixbuf);
@@ -147,7 +149,8 @@ void audio_waterfall_update() {
     memmove(&pixels[rowstride*(header+1)],&pixels[rowstride*header],(height-(header+1))*rowstride);
 
     float sample;
-    char *p;
+   // DL1YCF changed to uchar *
+    unsigned char *p;
     int average=0;
     p=&pixels[rowstride*header];
     for(i=0;i<width;i++) {
index ff020c2bea60cef4dcdf25e7bfad0fb853fec841..c82a3e8faae3b7b8491161cc134346ab1bfb7f24 100644 (file)
@@ -64,6 +64,10 @@ gboolean band_select_cb (GtkWidget *widget, gpointer        data) {
   last_band=widget;
   set_button_text_color(last_band,"orange");
   vfo_band_changed(b);
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void band_menu(GtkWidget *parent) {
index d5a1b4f3909b09d212442708d2e3e0d657633cdb..aa05ff04d08347049b18575fc652873b61d9c420 100644 (file)
@@ -63,6 +63,10 @@ static gboolean bandstack_select_cb (GtkWidget *widget, gpointer        data) {
   last_bandstack=widget;
   set_button_text_color(last_bandstack,"orange");
   vfo_bandstack_changed(b);
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void bandstack_menu(GtkWidget *parent) {
index 09ce55331e3a78bb71d0986be7807303715a5c5d..73ea8c7a6a65a11be4bdad63782990a0a9c2118d 100644 (file)
@@ -70,7 +70,8 @@ static void pre_post_agc_cb(GtkWidget *widget, gpointer data) {
 }
 
 static void nr2_gain_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->nr2_gain_method==(uintptr_t)data;
+// DL1YCF changed == to =
+  active_receiver->nr2_gain_method=(uintptr_t)data;
   SetRXAEMNRgainMethod(active_receiver->id, active_receiver->nr2_gain_method);
 }
 
index 514e77d609607eb803e006feca7f776f56a71f8a..325c24922d2e54f5c6ae49f5baaca5b4377dece1 100644 (file)
@@ -70,6 +70,10 @@ static gboolean tx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
     gtk_range_set_value(GTK_RANGE(mid_scale),(double)tx_equalizer[2]);
     gtk_range_set_value(GTK_RANGE(high_scale),(double)tx_equalizer[3]);
   }
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static gboolean rx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -82,6 +86,10 @@ static gboolean rx_rb_cb (GtkWidget *widget, GdkEventButton *event, gpointer dat
     gtk_range_set_value(GTK_RANGE(mid_scale),(double)rx_equalizer[2]);
     gtk_range_set_value(GTK_RANGE(high_scale),(double)rx_equalizer[3]);
   }
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static gboolean enable_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) {
@@ -92,6 +100,10 @@ static gboolean enable_cb (GtkWidget *widget, GdkEventButton *event, gpointer da
     enable_rx_equalizer=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
     SetRXAEQRun(active_receiver->id, enable_rx_equalizer);
   }
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static void value_changed_cb (GtkWidget *widget, gpointer data) {
index 5c7313e6001614fee25fa07e03a8c02cc748a0d4..800b04d13c4a47881e0b546b98201255cbc833e1 100644 (file)
@@ -22,6 +22,10 @@ int show_error(void *data) {
   gtk_widget_show(label);
   timer=g_timeout_add(5000,timeout_cb,NULL);
   int result=gtk_dialog_run(GTK_DIALOG(dialog));
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void error_handler(char *text,char *err) {
diff --git a/ext.c b/ext.c
index 071736bbcd6ccdad2bdd31dbd388dc2b1a196bd1..c5ba6191fa33a0ee96783489fcbf9661960c305e 100644 (file)
--- a/ext.c
+++ b/ext.c
@@ -44,6 +44,10 @@ int ext_discovery(void *data) {
 int ext_set_frequency(void *data) {
   setFrequency(*(long long *)data);
   free(data);
+  // DL1YCF added return statement
+  // this one is CRITICAL to avoid free() being called 
+  // repeatedly on the same pointer
+  return 0;
 }
 
 int ext_vfo_update(void *data) {
@@ -67,14 +71,20 @@ int ext_band_update(void *data) {
 
 int ext_mode_update(void *data) {
   start_mode();
+  // DL1YCF added return statement
+  return 0;
 }
 
 int ext_filter_update(void *data) {
   start_filter();
+  // DL1YCF added return statement
+  return 0;
 }
 
 int ext_noise_update(void *data) {
   start_noise();
+  // DL1YCF added return statement
+  return 0;
 }
 
 int ext_ptt_update(void *data) {
index aee2b6840d4e54b4a9ff4ce04dbaf1ac2274f866..092d89060dc0894700da6fa8d35e37494f7e0fb3 100644 (file)
@@ -67,6 +67,10 @@ static gboolean filter_select_cb (GtkWidget *widget, gpointer        data) {
   set_button_text_color(last_filter,"black");
   last_filter=widget;
   set_button_text_color(last_filter,"orange");
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static gboolean deviation_select_cb (GtkWidget *widget, gpointer data) {
@@ -87,6 +91,10 @@ static gboolean deviation_select_cb (GtkWidget *widget, gpointer data) {
   last_filter=widget;
   set_button_text_color(last_filter,"orange");
   vfo_update();
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static void var_spin_low_cb (GtkWidget *widget, gpointer data) {
index 8028ad0f33d34db5d000a8400285a194242224cc..0370ff723273d069bc4973d673136887d601d637 100644 (file)
@@ -146,6 +146,8 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
         }
     }
     vfo_update();
+    // DL1YCF added return statement
+    return FALSE;
 }
 
 static GtkWidget *last_mode;
index 51026b56e7ebf773e431e7949c223f0b31b74ed9..71f250297c6f397ceb1949b66822b30fb5464fd5 100644 (file)
--- a/iambic.c
+++ b/iambic.c
@@ -116,7 +116,11 @@ static int kcwr = 0;
 int *kdot;
 int *kdash;
 static int running = 0;
+#ifdef __APPLE__
+static sem_t *cw_event;
+#else
 static sem_t cw_event;
+#endif
 
 int keyer_out = 0;
 
@@ -160,7 +164,11 @@ void keyer_event(int gpio, int level) {
         kcwr = state;
 
     if (state || cw_keyer_mode == KEYER_STRAIGHT) {
+#ifdef __APPLE__
+        sem_post(cw_event);
+#else
         sem_post(&cw_event);
+#endif
     }
 }
 #endif
@@ -197,7 +205,11 @@ static void* keyer_thread(void *arg) {
 
 fprintf(stderr,"keyer_thread  state running= %d\n", running);
     while(running) {
+#ifdef __APPLE__
+        sem_wait(cw_event);
+#else
         sem_wait(&cw_event);
+#endif
 
         key_state = CHECK;
 
@@ -390,7 +402,12 @@ int keyer_init() {
         softToneCreate(SIDETONE_GPIO);
     }
 
+#ifdef __APPLE__
+    cw_event=sem_open("CW", O_CREAT, 0700, 0);
+    rc = (cw_event == SEM_FAILED);
+#else
     rc = sem_init(&cw_event, 0, 0);
+#endif
     rc |= pthread_create(&keyer_thread_id, NULL, keyer_thread, NULL);
     running = 1;
     if(rc < 0) {
diff --git a/main.c b/main.c
index b17a210a2f8c85f0189926c4fad802bb419c09b3..4e3bcbca6c985e1c5b52a77f0b1345c916c3f533 100644 (file)
--- a/main.c
+++ b/main.c
 *
 */
 
+// DL1YCF
+// Define maximum window size. 
+// Original values 800 and 480, but if the screen is large, why not using it?
+
+#define MAX_DISPLAY_WIDTH 1020
+#define MAX_DISPLAY_HEIGHT 700
+
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 #include <math.h>
@@ -58,7 +65,11 @@ gint full_screen=1;
 
 static GtkWidget *discovery_dialog;
 
+#ifdef __APPLE__
+static sem_t *wisdom_sem;
+#else
 static sem_t wisdom_sem;
+#endif
 
 static GdkCursor *cursor_arrow;
 static GdkCursor *cursor_watch;
@@ -91,7 +102,12 @@ static void* wisdom_thread(void *arg) {
 fprintf(stderr,"Creating wisdom file: %s\n", (char *)arg);
   status_text("Creating FFTW Wisdom file ...");
   WDSPwisdom ((char *)arg);
+#ifdef __APPLE__
+  sem_post(wisdom_sem);
+#else
   sem_post(&wisdom_sem);
+#endif
+  return NULL;
 }
 
 gboolean main_delete (GtkWidget *widget) {
@@ -138,9 +154,18 @@ static int init(void *data) {
   strcpy(&wisdom_file[strlen(wisdom_file)],"wdspWisdom");
   status_text("Checking FFTW Wisdom file ...");
   if(access(wisdom_file,F_OK)<0) {
+#ifdef __APPLE__
+      int rc;
+      wisdom_sem=sem_open("WISDOM", O_CREAT, 0700, 0);
+#else
       int rc=sem_init(&wisdom_sem, 0, 0);
+#endif
       rc=pthread_create(&wisdom_thread_id, NULL, wisdom_thread, (void *)wisdom_directory);
+#ifdef __APPLE__
+      while(sem_trywait(wisdom_sem)<0) {
+#else
       while(sem_trywait(&wisdom_sem)<0) {
+#endif
         status_text(wisdom_get_status());
         while (gtk_events_pending ())
           gtk_main_iteration ();
@@ -178,21 +203,11 @@ static void activate_pihpsdr(GtkApplication *app, gpointer data) {
   display_height=gdk_screen_get_height(screen);
 
 fprintf(stderr,"width=%d height=%d\n", display_width, display_height);
-  if(display_width>800 || display_height>480) {
-/*
-    if(display_width>1600) {
-      display_width=1600;
-    } else {
-      display_width=800;
-    }
-    if(display_height>960) {
-      display_height=960;
-    } else {
-      display_height=480;
-    }
-*/
-    display_width=800;
-    display_height=480;
+
+  // DL1YCF: use define'd constants here
+  if(display_width>MAX_DISPLAY_WIDTH || display_height>MAX_DISPLAY_HEIGHT) {
+    display_width=MAX_DISPLAY_WIDTH;
+    display_height=MAX_DISPLAY_HEIGHT;
     full_screen=0;
   }
 
index b2c02bb394639bacb7b71ac2645de8c959bacdbc..d40eee339e77c884fb4ef1f8e6bea89331946ec4 100644 (file)
@@ -64,6 +64,10 @@ static gboolean mode_select_cb (GtkWidget *widget, gpointer        data) {
   last_mode=widget;
   set_button_text_color(last_mode,"orange");
   vfo_mode_changed(m);
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void mode_menu(GtkWidget *parent) {
index 8ab5f888c1152d690b70afe6141b36d684d8c09e..634d99d349190f3b7eae1172be31806e25365f5a 100644 (file)
@@ -185,7 +185,8 @@ void new_discover(struct ifaddrs* iface) {
 //void* new_discover_receive_thread(void* arg) {
 gpointer new_discover_receive_thread(gpointer data) {
     struct sockaddr_in addr;
-    int len;
+    // DL1YCF change from int to socklen_t
+    socklen_t len;
     unsigned char buffer[2048];
     int bytes_read;
     struct timeval tv;
@@ -275,4 +276,6 @@ gpointer new_discover_receive_thread(gpointer data) {
     }
     fprintf(stderr,"new_discover: exiting new_discover_receive_thread\n");
     g_thread_exit(NULL);
+    // DL1YCF added return statement to make compiler happy.
+    return NULL;
 }
index 78da6c8e7b9ad61f69253b50b7b0612c1e3f42de..93d84a9ade31729e58937d59353ed185fbdf5524 100644 (file)
@@ -73,7 +73,18 @@ int data_socket=-1;
 
 static int running;
 
+#ifdef __APPLE__
+//
+//DL1YCF:
+//Mac OS does not have sem_init for un-named semaphores,
+//we have to use named semaphores created with sem_open.
+//As a side effect, we consistently have to use sem_t
+//pointers instead of sem_t variables
+//
+sem_t *response_sem;
+#else
 sem_t response_sem;
+#endif
 
 static struct sockaddr_in base_addr;
 static int base_addr_length;
@@ -137,17 +148,37 @@ static int response;
 //static sem_t send_general_sem;
 //static int send_general=0;
 
+#ifdef __APPLE__
+static sem_t *command_response_sem_ready;
+static sem_t *command_response_sem_buffer;
+#else
 static sem_t command_response_sem_ready;
 static sem_t command_response_sem_buffer;
+#endif
 static GThread *command_response_thread_id;
+#ifdef __APPLE__
+static sem_t *high_priority_sem_ready;
+static sem_t *high_priority_sem_buffer;
+#else
 static sem_t high_priority_sem_ready;
 static sem_t high_priority_sem_buffer;
+#endif
 static GThread *high_priority_thread_id;
+#ifdef __APPLE__
+static sem_t *mic_line_sem_ready;
+static sem_t *mic_line_sem_buffer;
+#else
 static sem_t mic_line_sem_ready;
 static sem_t mic_line_sem_buffer;
+#endif
 static GThread *mic_line_thread_id;
+#ifdef __APPLE__
+static sem_t *iq_sem_ready[MAX_RECEIVERS];
+static sem_t *iq_sem_buffer[MAX_RECEIVERS];
+#else
 static sem_t iq_sem_ready[MAX_RECEIVERS];
 static sem_t iq_sem_buffer[MAX_RECEIVERS];
+#endif
 static GThread *iq_thread_id[MAX_RECEIVERS];
 
 static int samples[MAX_RECEIVERS];
@@ -169,7 +200,8 @@ static int psk_resample=6;  // convert from 48000 to 8000
 #define NET_BUFFER_SIZE 2048
 // Network buffers
 static struct sockaddr_in addr;
-static int length;
+// DL1YCF next line: changed int to socklen_t
+static socklen_t length;
 //static unsigned char buffer[NET_BUFFER_SIZE];
 static unsigned char *iq_buffer[MAX_RECEIVERS];
 static unsigned char *command_response_buffer;
@@ -296,28 +328,47 @@ void new_protocol_init(int pixels) {
     new_protocol_calc_buffers();
 #endif
 
+#ifdef __APPLE__
+    response_sem=sem_open("RESPONSE", O_CREAT, 0700, 0);
+#else
     rc=sem_init(&response_sem, 0, 0);
+#endif
     //rc=sem_init(&send_high_priority_sem, 0, 1);
     //rc=sem_init(&send_general_sem, 0, 1);
 
+#ifdef __APPLE__
+    command_response_sem_ready=sem_open("COMMRESREADY", O_CREAT, 0700, 0);
+    command_response_sem_buffer=sem_open("COMMRESBUF", O_CREAT, 0700, 0);
+#else
     rc=sem_init(&command_response_sem_ready, 0, 0);
     rc=sem_init(&command_response_sem_buffer, 0, 0);
+#endif
     command_response_thread_id = g_thread_new( "command_response thread",command_response_thread, NULL);
     if( ! command_response_thread_id ) {
       fprintf(stderr,"g_thread_new failed on command_response_thread\n");
       exit( -1 );
     }
     fprintf(stderr, "command_response_thread: id=%p\n",command_response_thread_id);
+#ifdef __APPLE__
+    high_priority_sem_ready=sem_open("HIGHREADY", O_CREAT, 0700, 0);
+    high_priority_sem_buffer=sem_open("HIGHBUF",   O_CREAT, 0700, 0);
+#else
     rc=sem_init(&high_priority_sem_ready, 0, 0);
     rc=sem_init(&high_priority_sem_buffer, 0, 0);
+#endif
     high_priority_thread_id = g_thread_new( "high_priority thread", high_priority_thread, NULL);
     if( ! high_priority_thread_id ) {
       fprintf(stderr,"g_thread_new failed on high_priority_thread\n");
       exit( -1 );
     }
     fprintf(stderr, "high_priority_thread: id=%p\n",high_priority_thread_id);
+#ifdef __APPLE__
+    mic_line_sem_ready=sem_open("MICREADY", O_CREAT, 0700, 0);
+    mic_line_sem_buffer=sem_open("MICBUF",   O_CREAT, 0700, 0);
+#else
     rc=sem_init(&mic_line_sem_ready, 0, 0);
     rc=sem_init(&mic_line_sem_buffer, 0, 0);
+#endif
     mic_line_thread_id = g_thread_new( "mic_line thread", mic_line_thread, NULL);
     if( ! mic_line_thread_id ) {
       fprintf(stderr,"g_thread_new failed on mic_line_thread\n");
@@ -326,23 +377,45 @@ void new_protocol_init(int pixels) {
     fprintf(stderr, "mic_line_thread: id=%p\n",mic_line_thread_id);
 
     for(i=0;i<RECEIVERS;i++) {
+#ifdef __APPLE__
+      char sname[12];
+#endif
       ddc=receiver[i]->ddc;
+#ifdef __APPLE__
+      sprintf(sname,"IQREADY%03d", ddc);
+      iq_sem_ready[ddc]=sem_open(sname, O_CREAT, 0700, 0);
+      sprintf(sname,"IQBUF%03d", ddc);
+      iq_sem_buffer[ddc]=sem_open(sname, O_CREAT, 0700, 0);
+#else
       rc=sem_init(&iq_sem_ready[ddc], 0, 0);
       rc=sem_init(&iq_sem_buffer[ddc], 0, 0);
+#endif
       iq_thread_id[ddc] = g_thread_new( "iq thread", iq_thread, (gpointer)(long)i);
-      if( ! iq_thread_id ) {
-        fprintf(stderr,"g_thread_new failed for iq_thread: rx=%d\n",i);
-        exit( -1 );
-      }
+      //DL1YCF: g_thread new always returns a value, upon failure the program aborts
+      //        so the next four lines have been deactivated.
+      //if( ! iq_thread_id ) {
+      //  fprintf(stderr,"g_thread_new failed for iq_thread: rx=%d\n",i);
+      //  exit( -1 );
+      //}
       fprintf(stderr, "iq_thread: rx=%d ddc=%d thread=%p\n",i, ddc, iq_thread_id);
     }
 
 #ifdef PURESIGNAL
     // for PS the two feedback streams are synced on the one DDC
     if(device!=NEW_DEVICE_HERMES) {
+#ifdef __APPLE__
+      char sname[12];
+#endif
       ddc=receiver[PS_TX_FEEDBACK]->ddc;
+#ifdef __APPLE__
+      sprintf(sname,"IQREADY%03d", ddc);
+      iq_sem_ready[ddc]=sem_open(sname, O_CREAT, 0700, 0);
+      sprintf(sname,"IQBUF%03d", ddc);
+      iq_sem_buffer[ddc]=sem_open(sname, O_CREAT, 0700, 0);
+#else
       rc=sem_init(&iq_sem_ready[ddc], 0, 0);
       rc=sem_init(&iq_sem_buffer[ddc], 0, 0);
+#endif
       iq_thread_id[ddc] = g_thread_new( "ps iq thread", ps_iq_thread, (gpointer)(long)PS_TX_FEEDBACK);
       if( ! iq_thread_id ) {
         fprintf(stderr,"g_thread_new failed for ps_iq_thread: rx=%d\n",PS_TX_FEEDBACK);
@@ -1144,28 +1217,60 @@ fprintf(stderr,"new_protocol_thread: high_priority_addr setup for port %d\n",HIG
               if(ddc>=MAX_RECEIVERS)  {
                 fprintf(stderr,"unexpected iq data from ddc %d\n",ddc);
               } else {
+#ifdef __APPLE__
+                sem_wait(iq_sem_ready[ddc]);
+#else
                 sem_wait(&iq_sem_ready[ddc]);
+#endif
                 iq_buffer[ddc]=buffer;
+#ifdef __APPLE__
+                sem_post(iq_sem_buffer[ddc]);
+#else
                 sem_post(&iq_sem_buffer[ddc]);
+#endif
               }
               break;
             case COMMAND_RESPONCE_TO_HOST_PORT:
+#ifdef __APPLE__
+              sem_wait(command_response_sem_ready);
+#else
               sem_wait(&command_response_sem_ready);
+#endif
               command_response_buffer=buffer;
+#ifdef __APPLE__
+              sem_post(command_response_sem_buffer);
+#else
               sem_post(&command_response_sem_buffer);
+#endif
               //process_command_response();
               break;
             case HIGH_PRIORITY_TO_HOST_PORT:
+#ifdef __APPLE__
+              sem_wait(high_priority_sem_ready);
+#else
               sem_wait(&high_priority_sem_ready);
+#endif
               high_priority_buffer=buffer;
+#ifdef __APPLE__
+              sem_post(high_priority_sem_buffer);
+#else
               sem_post(&high_priority_sem_buffer);
+#endif
               //process_high_priority();
               break;
             case MIC_LINE_TO_HOST_PORT:
+#ifdef __APPLE__
+              sem_wait(mic_line_sem_ready);
+#else
               sem_wait(&mic_line_sem_ready);
+#endif
               mic_line_buffer=buffer;
               mic_bytes_read=bytesread;
+#ifdef __APPLE__
+              sem_post(mic_line_sem_buffer);
+#else
               sem_post(&mic_line_sem_buffer);
+#endif
               break;
             default:
 fprintf(stderr,"new_protocol_thread: Unknown port %d\n",sourceport);
@@ -1175,13 +1280,19 @@ fprintf(stderr,"new_protocol_thread: Unknown port %d\n",sourceport);
     }
 
     close(data_socket);
+    return NULL;
 }
 
 static gpointer command_response_thread(gpointer data) {
   while(1) {
 fprintf(stderr,"command_response_thread\n");
+#ifdef __APPLE__
+    sem_post(command_response_sem_ready);
+    sem_wait(command_response_sem_buffer);
+#else
     sem_post(&command_response_sem_ready);
     sem_wait(&command_response_sem_buffer);
+#endif
     process_command_response();
     free(command_response_buffer);
   }
@@ -1190,8 +1301,13 @@ fprintf(stderr,"command_response_thread\n");
 static gpointer high_priority_thread(gpointer data) {
 fprintf(stderr,"high_priority_thread\n");
   while(1) {
+#ifdef __APPLE__
+    sem_post(high_priority_sem_ready);
+    sem_wait(high_priority_sem_buffer);
+#else
     sem_post(&high_priority_sem_ready);
     sem_wait(&high_priority_sem_buffer);
+#endif
     process_high_priority();
     free(high_priority_buffer);
   }
@@ -1200,8 +1316,13 @@ fprintf(stderr,"high_priority_thread\n");
 static gpointer mic_line_thread(gpointer data) {
 fprintf(stderr,"mic_line_thread\n");
   while(1) {
+#ifdef __APPLE__
+    sem_post(mic_line_sem_ready);
+    sem_wait(mic_line_sem_buffer);
+#else
     sem_post(&mic_line_sem_ready);
     sem_wait(&mic_line_sem_buffer);
+#endif
     if(!transmitter->local_microphone) {
       process_mic_data(mic_bytes_read);
     }
@@ -1214,8 +1335,13 @@ static gpointer iq_thread(gpointer data) {
   int ddc=receiver[rx]->ddc;
 fprintf(stderr,"iq_thread: rx=%d ddc=%d\n",rx,ddc);
   while(1) {
+#ifdef __APPLE__
+    sem_post(iq_sem_ready[ddc]);
+    sem_wait(iq_sem_buffer[ddc]);
+#else
     sem_post(&iq_sem_ready[ddc]);
     sem_wait(&iq_sem_buffer[ddc]);
+#endif
     process_iq_data(receiver[rx]);
     free(iq_buffer[ddc]);
   }
@@ -1227,8 +1353,13 @@ static gpointer ps_iq_thread(gpointer data) {
   int ddc=receiver[rx]->ddc;
 fprintf(stderr,"ps_iq_thread: rx=%d ddc=%d\n",rx,ddc);
   while(1) {
+#ifdef __APPLE__
+    sem_post(iq_sem_ready[ddc]);
+    sem_wait(iq_sem_buffer[ddc]);
+#else
     sem_post(&iq_sem_ready[ddc]);
     sem_wait(&iq_sem_buffer[ddc]);
+#endif
     process_ps_iq_data(receiver[rx]);
     free(iq_buffer[ddc]);
   }
@@ -1257,7 +1388,8 @@ static void process_iq_data(RECEIVER *rx) {
   }
   rx->iq_sequence++;
 
-  timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32);
+// DL1YCF: changed semicolon at end of next line to a plus sign
+  timestamp=((long long)(buffer[4]&0xFF)<<56)+((long long)(buffer[5]&0xFF)<<48)+((long long)(buffer[6]&0xFF)<<40)+((long long)(buffer[7]&0xFF)<<32)+
   ((long long)(buffer[8]&0xFF)<<24)+((long long)(buffer[9]&0xFF)<<16)+((long long)(buffer[10]&0xFF)<<8)+(long long)(buffer[11]&0xFF);
   bitspersample=((buffer[12]&0xFF)<<8)+(buffer[13]&0xFF);
   samplesperframe=((buffer[14]&0xFF)<<8)+(buffer[15]&0xFF);
@@ -1378,7 +1510,11 @@ static void process_command_response() {
     response_sequence=((command_response_buffer[0]&0xFF)<<24)+((command_response_buffer[1]&0xFF)<<16)+((command_response_buffer[2]&0xFF)<<8)+(command_response_buffer[3]&0xFF);
     response=command_response_buffer[4]&0xFF;
     fprintf(stderr,"response_sequence=%ld response=%d\n",response_sequence,response);
+#ifdef __APPLE__
+    sem_post(response_sem);
+#else
     sem_post(&response_sem);
+#endif
 }
 
 static void process_high_priority(unsigned char *buffer) {
@@ -1424,7 +1560,10 @@ static void process_mic_data(int bytes) {
   sequence=((mic_line_buffer[0]&0xFF)<<24)+((mic_line_buffer[1]&0xFF)<<16)+((mic_line_buffer[2]&0xFF)<<8)+(mic_line_buffer[3]&0xFF);
   b=4;
   for(i=0;i<MIC_SAMPLES;i++) {
-    sample=(short)((mic_line_buffer[b++]<<8) | (mic_line_buffer[b++]&0xFF));
+    // DL1YCF: changed this to two statements such that the order of pointer increments
+    //         becomes clearly defined.
+    sample=(short)(mic_line_buffer[b++]<<8);
+    sample |= (short) (mic_line_buffer[b++]&0xFF);
 #ifdef FREEDV
     if(active_receiver->freedv) {
       add_freedv_mic_sample(transmitter,sample);
@@ -1445,9 +1584,15 @@ void new_protocol_process_local_mic(unsigned char *buffer,int le) {
   b=0;
   for(i=0;i<MIC_SAMPLES;i++) {
     if(le) {
-      sample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
+      // DL1YCF: changed this to two statements such that the order of pointer increments
+      //         becomes clearly defined.
+      sample = (short)(buffer[b++]&0xFF);
+      sample |= (short) (buffer[b++]<<8);
     } else {
-      sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
+      // DL1YCF: changed this to two statements such that the order of pointer increments
+      //         becomes clearly defined.
+      sample = (short)(buffer[b++]<<8);
+      sample |= (short) (buffer[b++]&0xFF);
     }
 #ifdef FREEDV
     if(active_receiver->freedv) {
@@ -1533,4 +1678,6 @@ fprintf(stderr,"new_protocol_timer_thread\n");
 //      }
 //    }
   }
+  // DL1YCF: added return statement to make compiler happy.
+  return NULL;
 }
index fa0906782551378b75b5d974ee744d694b3930ac..659c7213bb1614c26658d99b2298244e968678f9 100644 (file)
 #define MIC_SAMPLES 64
 
 extern int data_socket;
+#ifdef __APPLE__
+extern sem_t *response_sem;
+#else
 extern sem_t response_sem;
+#endif
 
 /*
 extern long response_sequence;
index ea4daf821c220d67b85b7250c16d391958abd1e5..939ef04a5993876546d13f86c7723949beb93865 100644 (file)
@@ -172,7 +172,11 @@ void *programmer_thread(void *arg) {
     // wait for the response to the erase command
     clock_gettime(CLOCK_REALTIME, &ts);
     ts.tv_sec+=120; // wait for 30 seconds
+#ifdef __APPLE__
+    result=sem_trywait(response_sem);
+#else
     result=sem_timedwait(&response_sem,&ts);
+#endif
     if(result==-1) {
         if(errno == ETIMEDOUT) {
             fprintf(stderr,"timedout waiting for response for erase (start)\n");
@@ -190,7 +194,11 @@ void *programmer_thread(void *arg) {
     // wait for the erase to complete
     clock_gettime(CLOCK_REALTIME, &ts);
     ts.tv_sec+=120; // wait for 30 seconds
+#ifdef __APPLE__
+    result=sem_trywait(response_sem);
+#else
     result=sem_timedwait(&response_sem,&ts);
+#endif
     if(result==-1) {
         if(errno == ETIMEDOUT) {
             fprintf(stderr,"timedout waiting for response for erase (complete)\n");
@@ -211,7 +219,11 @@ void *programmer_thread(void *arg) {
         programmer_send_block(b);
         clock_gettime(CLOCK_REALTIME, &ts);
         ts.tv_sec+=5; // wait for 5 seconds
+#ifdef __APPLE__
+        result=sem_trywait(response_sem);
+#else
         result=sem_timedwait(&response_sem,&ts);
+#endif
         if(result==-1) {
             if(errno == ETIMEDOUT) {
                 fprintf(stderr,"timedout waiting for response for sent block\n");
@@ -227,5 +239,7 @@ void *programmer_thread(void *arg) {
         }
         block_sequence++;
     }
-    
+
+    // DL1YCF added return statement to make compiler happy.
+    return NULL;    
 }
index 57ea09e3ce80e86716d8e5870d11b1dc7d2273c7..e47c4656b7db9b6cf481f6bbcddaef31e97c3de5 100644 (file)
@@ -133,7 +133,8 @@ static void discover(struct ifaddrs* iface) {
 //static void *discover_receive_thread(void* arg) {
 static gpointer discover_receive_thread(gpointer data) {
     struct sockaddr_in addr;
-    int len;
+    // DL1YCF changed int to socklen_t
+    socklen_t len;
     unsigned char buffer[2048];
     int bytes_read;
     struct timeval tv;
@@ -183,6 +184,7 @@ fprintf(stderr,"discover_receive_thread\n");
                                                        #else
                                                                strcpy(discovered[devices].name,"Hermes Lite");         
                                                        #endif
+
                             break;
                         case DEVICE_ORION2:
                             strcpy(discovered[devices].name,"Orion 2");
@@ -222,6 +224,8 @@ fprintf(stderr,"discover_receive_thread\n");
     }
     fprintf(stderr,"discovery: exiting discover_receive_thread\n");
     g_thread_exit(NULL);
+    // DL1YCF added return statement to make compiler happy.
+    return NULL;
 }
 
 void old_discovery() {
index 3459bec24ad939ca844e8c5cd1472c28f5af3767..8b2aa128e0b355849ebd8c8167b5217785a03442 100644 (file)
@@ -131,6 +131,9 @@ static double phase=0.0;
 static int running;
 static long ep4_sequence;
 
+// DL1YCF added this variable for lost-package-check
+static long last_seq_num=0;
+
 static int current_rx=0;
 
 static int samples=0;
@@ -161,7 +164,8 @@ static int command=1;
 static GThread *receive_thread_id;
 static void start_receive_thread();
 static gpointer receive_thread(gpointer arg);
-static void process_ozy_input_buffer(char  *buffer);
+// DL1YCF changed buffer to uchar*
+static void process_ozy_input_buffer(unsigned char  *buffer);
 static void process_bandscope_buffer(char  *buffer);
 void ozy_send_buffer();
 
@@ -169,9 +173,11 @@ static unsigned char metis_buffer[1032];
 static long send_sequence=-1;
 static int metis_offset=8;
 
-static int metis_write(unsigned char ep,char* buffer,int length);
+// DL1YCF changed buffer to uchar*
+static int metis_write(unsigned char ep,unsigned char* buffer,int length);
 static void metis_start_stop(int command);
-static void metis_send_buffer(char* buffer,int length);
+// DL1YCF changed buffer to uchar*
+static void metis_send_buffer(unsigned char* buffer,int length);
 static void metis_restart();
 
 #define COMMON_MERCURY_FREQUENCY 0x80
@@ -374,7 +380,8 @@ static void start_receive_thread() {
 
 static gpointer receive_thread(gpointer arg) {
   struct sockaddr_in addr;
-  int length;
+  // DL1YCF changed from int to socklen_t
+  socklen_t length;
   unsigned char buffer[2048];
   int bytes_read;
   int ep;
@@ -414,6 +421,11 @@ static gpointer receive_thread(gpointer arg) {
               // get the sequence number
               sequence=((buffer[4]&0xFF)<<24)+((buffer[5]&0xFF)<<16)+((buffer[6]&0xFF)<<8)+(buffer[7]&0xFF);
 
+             // DL1YCF: added check on lost packets
+              if (sequence != last_seq_num+1) {
+               fprintf(stderr,"SEQ ERROR: last %ld, recvd %ld\n", last_seq_num, sequence);
+             }
+             last_seq_num=sequence;
               switch(ep) {
                 case 6: // EP6
                   // process the data
@@ -453,9 +465,12 @@ static gpointer receive_thread(gpointer arg) {
         break;
     }
   }
+  // DL1YCF added return statement to make compiler happy.
+  return NULL;
 }
 
-static void process_ozy_input_buffer(char  *buffer) {
+// Dl1YCF changed buffer to uchar*
+static void process_ozy_input_buffer(unsigned char  *buffer) {
   int i,j;
   int r;
   int b=0;
@@ -702,10 +717,18 @@ void old_protocol_process_local_mic(unsigned char *buffer,int le) {
 // always 48000 samples per second
   b=0;
   for(i=0;i<720;i++) {
+    // avoid pointer increments in logical-or constructs, as the sequence
+    // is undefined
     if(le) {
-      sample = (short)((buffer[b++]&0xFF) | (buffer[b++]<<8));
+      // DL1YCF: changed this to two statements such that the order of pointer increments
+      //         becomes clearly defined.
+      sample = (short) (buffer[b++]&0xFF);
+      sample |= (short) (buffer[b++]<<8);
     } else {
-      sample = (short)((buffer[b++]<<8) | (buffer[b++]&0xFF));
+      // DL1YCF: changed this to two statements such that the order of pointer increments
+      //         becomes clearly defined.
+      sample = (short)(buffer[b++]<<8);
+      sample |=  (short) (buffer[b++]&0xFF);
     }
 #ifdef FREEDV
     if(active_receiver->freedv) {
@@ -724,7 +747,10 @@ static void process_bandscope_buffer(char  *buffer) {
 }
 */
 
-
+#ifdef PROTOCOL_DEBUG
+// DL1YCF Debug: save last values and log changes
+static unsigned char last_c1[20], last_c2[20], last_c3[20], last_c4[20], last_mox;
+#endif
 
 void ozy_send_buffer() {
 
@@ -986,7 +1012,25 @@ void ozy_send_buffer() {
         {
         BAND *band=band_get_current_band();
         int power=0;
+#ifdef STEMLAB_FIX
+       //
+       // DL1YCF:
+       // On my HAMlab RedPitaya-based SDR transceiver, CW is generated on-board the RP.
+       // However, while in CW mode, DriveLevel changes do not become effective.
+       // If the CW paddle is hit, the new PTT state is sent to piHPSDR, then the TX drive
+       // is sent the next time "command 3" is performed, but this often is too late and
+       // CW is generated with zero DriveLevel.
+       // Therefore, when in CW mode, send the TX drive level also when receiving.
+       //
+        if(split) {
+          mode=vfo[1].mode;
+        } else {
+          mode=vfo[0].mode;
+        }
+        if(isTransmitting() || (mode == modeCWU) || (mode == modeCWL)) {
+#else
         if(isTransmitting()) {
+#endif
           if(tune && !transmitter->tune_use_drive) {
             power=(int)((double)transmitter->drive_level/100.0*(double)transmitter->tune_percent);
           } else {
@@ -1166,6 +1210,37 @@ void ozy_send_buffer() {
     }
   }
 
+#ifdef PROTOCOL_DEBUG
+//
+// DL1YCF debug:
+// look for changed parameters and log them
+// This is great for debugging protocol problems,
+// such as the HAMlab CW error fixed above, so I
+// leave it here deactivated
+//
+  int ind = output_buffer[C0] >> 1;
+  if (last_c1[ind] != output_buffer[C1]) {
+    fprintf(stderr, "C0=%x Old C1=%x New C1=%x\n", 2*ind,last_c1[ind], output_buffer[C1]);
+    last_c1[ind]=output_buffer[C1];
+  }
+  if (last_c2[ind] != output_buffer[C2]) {
+    fprintf(stderr, "C0=%x Old C2=%x New C2=%x\n", 2*ind,last_c2[ind], output_buffer[C2]);
+    last_c2[ind]=output_buffer[C2];
+  }
+  if (last_c3[ind] != output_buffer[C3]) {
+    fprintf(stderr, "C0=%x Old C3=%x New C3=%x\n", 2*ind,last_c3[ind], output_buffer[C3]);
+    last_c3[ind]=output_buffer[C3];
+  }
+  if (last_c4[ind] != output_buffer[C4]) {
+    fprintf(stderr, "C0=%x Old C4=%x New C4=%x\n", 2*ind,last_c4[ind], output_buffer[C4]);
+    last_c4[ind]=output_buffer[C4];
+  }
+  if ((output_buffer[C0] & 1) != last_mox) {
+    fprintf(stderr, "Last Mox=%d New Mox=%d\n", last_mox, output_buffer[C0] & 1);
+    last_mox=output_buffer[C0] & 1;
+  }
+#endif
+
 #ifdef USBOZY
 //
 // if we have a USB interfaced Ozy device:
@@ -1215,7 +1290,8 @@ static int ozyusb_write(char* buffer,int length)
 }
 #endif
 
-static int metis_write(unsigned char ep,char* buffer,int length) {
+// DL1YCF change buffer to uchar*
+static int metis_write(unsigned char ep,unsigned char* buffer,int length) {
   int i;
 
   // copy the buffer over
@@ -1248,11 +1324,33 @@ static int metis_write(unsigned char ep,char* buffer,int length) {
 
 static void metis_restart() {
   // reset metis frame
-  metis_offset==8;
+  // DL1YCF change == to = in the next line
+  metis_offset=8;
 
   // reset current rx
   current_rx=0;
 
+#ifdef STEMLAB_FIX
+  // DL1YCF:
+  // My RedPitaya HPSDR "clone" won't start up
+  // if too many commands are sent here. Note these
+  // packets are only there for sync-ing in the clock
+  // source etc.
+  // Note that always two 512-byte OZY buffers are
+  // combined into one METIS packet.
+  //
+  command=1;   // ship out a "C0=0" and a "set tx" command
+  ozy_send_buffer();
+  ozy_send_buffer();
+  command=2;  // ship out a "C0=0" and a "set rx" command for RX1
+  ozy_send_buffer();
+  ozy_send_buffer();
+
+  // DL1YCF: reset for the next commands
+  current_rx=0;
+  command=1;
+#else
+  // DL1YCF this is the original code, which does not do what it pretends ....
   // send commands twice
   command=1;
   do {
@@ -1262,6 +1360,7 @@ static void metis_restart() {
   do {
     ozy_send_buffer();
   } while (command!=1);
+#endif
 
   sleep(1);
 
@@ -1293,7 +1392,8 @@ static void metis_start_stop(int command) {
 #endif
 }
 
-static void metis_send_buffer(char* buffer,int length) {
+// DL1YCF changedbuffer to uchar *
+static void metis_send_buffer(unsigned char* buffer,int length) {
   if(sendto(data_socket,buffer,length,0,(struct sockaddr*)&data_addr,data_addr_length)!=length) {
     perror("sendto socket failed for metis_send_data\n");
   }
diff --git a/portaudio.c b/portaudio.c
new file mode 100644 (file)
index 0000000..69f77fc
--- /dev/null
@@ -0,0 +1,396 @@
+#ifdef PORTAUDIO
+//
+// DL1YCF: if PortAudio is NOT used, this file is empty, and audio.c
+//         is used instead.
+//         Here we also implement two (hopefully useful) functions:
+//         - a dummy two-tone 'Microphone' device
+//
+
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sched.h>
+#include <semaphore.h>
+
+#include "new_protocol.h"
+#include "old_protocol.h"
+#ifdef RADIOBERRY
+#include "radioberry.h"
+#endif
+#include "radio.h"
+#include "receiver.h"
+#include "portaudio.h"
+#include "math.h"   // for sintab, two-tone generator
+
+static PaStream *record_handle=NULL;
+
+#define MAXDEVICES 12
+
+const char *input_devices[MAXDEVICES];
+const char *output_devices[MAXDEVICES];
+
+int n_input_devices=0;
+int n_output_devices=0;
+
+static int   in_device_no[MAXDEVICES];
+static int   out_device_no[MAXDEVICES];
+
+static unsigned char *mic_buffer=NULL;
+static int mic_buffer_size;
+static int audio_buffer_size=256;
+
+//
+// Dummy Two-tone input device
+//
+static int TwoTone=0;
+#define lentab 480
+static float sintab[lentab];
+static int tonept;
+#define twopi 6.2831853071795864769252867665590
+#define factab (twopi/480)
+
+
+//
+// AUDIO_GET_CARDS
+//
+// This inits PortAudio and looks for suitable input and output channels
+//
+void audio_get_cards()
+{
+  int i, numDevices;
+  const PaDeviceInfo *deviceInfo;
+  PaStreamParameters inputParameters, outputParameters;
+
+  PaError err;
+
+  // generate sine tab
+  for (i=0; i< lentab; i++) sintab[i] = 0.35*(sin(7*i*factab)+sin(19*i*factab));
+
+  err = Pa_Initialize();
+  if( err != paNoError )
+  {
+       fprintf(stderr, "PORTAUDIO ERROR: Pa_Initialize: %s\n", Pa_GetErrorText(err));
+       return;
+  }
+  numDevices = Pa_GetDeviceCount();
+  if( numDevices < 0 ) return;
+
+  n_input_devices=0;
+  n_output_devices=0;
+
+  for( i=0; i<numDevices; i++ )
+  {
+       deviceInfo = Pa_GetDeviceInfo( i );
+
+        inputParameters.device = i;
+        inputParameters.channelCount = 1;
+        inputParameters.sampleFormat = paFloat32;
+        inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
+        inputParameters.hostApiSpecificStreamInfo = NULL;
+        if (Pa_IsFormatSupported(&inputParameters, NULL, 48000.0) == paFormatIsSupported) {
+          // duplicate the first suitable device, this will become
+          // a dummy two-tone generator
+          if (n_input_devices == 0) {
+            input_devices[n_input_devices]="TwoTone";
+            in_device_no[n_input_devices++] =i;
+          }
+          if (n_input_devices < MAXDEVICES) {
+            input_devices[n_input_devices]=deviceInfo->name;
+            in_device_no[n_input_devices++] =i;
+          }
+          fprintf(stderr,"PORTAUDIO INPUT DEVICE, No=%d, Name=%s\n", i, deviceInfo->name);
+       }
+
+       outputParameters.device = i;
+        outputParameters.channelCount = 1;
+        outputParameters.sampleFormat = paFloat32;
+        outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
+        outputParameters.hostApiSpecificStreamInfo = NULL;
+        if (Pa_IsFormatSupported(NULL, &outputParameters, 48000.0) == paFormatIsSupported) {
+          if (n_output_devices < MAXDEVICES) {
+            output_devices[n_output_devices]=deviceInfo->name;
+            out_device_no[n_output_devices++] =i;
+          }
+          fprintf(stderr,"PORTAUDIO OUTPUT DEVICE, No=%d, Name=%s\n", i, deviceInfo->name);
+        }
+  }
+}
+
+//
+// AUDIO_OPEN_INPUT
+//
+// open a PA stream that connects to the TX microphone
+// The PA callback function then sends the data to the transmitter
+//
+
+int pa_mic_cb(const void*, void*, unsigned long, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void*);
+unsigned char *micbuffer = NULL;
+
+int audio_open_input()
+{
+  PaError err;
+  PaStreamParameters inputParameters, outputParameters;
+  long framesPerBuffer;
+  int i;
+
+  fprintf(stderr,"audio_open_input: %d\n",transmitter->input_device);
+  if(transmitter->input_device<0 || transmitter->input_device>=n_input_devices) {
+    transmitter->input_device=0;
+    return -1;
+  }
+
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      framesPerBuffer = 720;
+      break;
+    case NEW_PROTOCOL:
+      framesPerBuffer = 64;
+      break;
+#ifdef RADIOBERRY
+        case RADIOBERRY_PROTOCOL:
+                framesPerBuffer = 1024;
+                break;
+#endif
+    default:
+      break;
+  }
+
+  bzero( &inputParameters, sizeof( inputParameters ) ); //not necessary if you are filling in all the fields
+  inputParameters.channelCount = 1;
+  inputParameters.device = in_device_no[transmitter->input_device];
+  inputParameters.hostApiSpecificStreamInfo = NULL;
+  inputParameters.sampleFormat = paFloat32;
+  inputParameters.suggestedLatency = Pa_GetDeviceInfo(in_device_no[transmitter->input_device])->defaultLowInputLatency ;
+  inputParameters.hostApiSpecificStreamInfo = NULL; //See you specific host's API docs for info on using this field
+
+  err = Pa_OpenStream(&record_handle, &inputParameters, NULL, 48000.0, framesPerBuffer, paNoFlag, pa_mic_cb, NULL);
+  if (err != paNoError) {
+    fprintf(stderr, "PORTAUDIO ERROR: AOI open stream: %s\n",Pa_GetErrorText(err));
+    return -1;
+  }
+
+  err = Pa_StartStream(record_handle);
+  if (err != paNoError) {
+    fprintf(stderr, "PORTAUDIO ERROR: AOI start stream:%s\n",Pa_GetErrorText(err));
+    return -1;
+  }
+  mic_buffer=(unsigned char *)malloc(2*framesPerBuffer);
+  mic_buffer_size=framesPerBuffer;
+  TwoTone=0;
+  if (transmitter->input_device == 0) {
+    tonept=0;
+    TwoTone=1;
+  }
+  return 0;
+}
+
+//
+// PortAudio call-back function for Audio input
+//
+int pa_mic_cb(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer,
+             const PaStreamCallbackTimeInfo* timeInfo,
+             PaStreamCallbackFlags statusFlags,
+             void *userdata)
+{
+  const float *in = (float *)inputBuffer;
+  int i;
+  short isample;
+  unsigned char *p;
+
+//
+// Convert input buffer in paFloat32 into a sequence of 16-bit
+// values in the mic buffer
+//
+  if (mic_buffer == NULL) return paAbort;
+
+  p=mic_buffer;
+  if (in == NULL || framesPerBuffer != mic_buffer_size) {
+    for (i=0; i<mic_buffer_size; i++)  {
+      *p++ = 0;
+      *p++ = 0;
+    }
+  } else if (TwoTone == 0) {
+    for (i=0; i<framesPerBuffer; i++) {
+      isample=(short) (in[i]*32768.0);
+      *p++   = (isample & 0xFF);      // LittleEndian
+      *p++ = (isample >> 8)& 0xFF;
+    }
+  } else {
+    for (i=0; i<framesPerBuffer; i++) {
+      isample=(short) (sintab[tonept++]*32768.0);
+      if (tonept == lentab) tonept=0;
+      *p++   = (isample & 0xFF);      // LittleEndian
+      *p++ = (isample >> 8)& 0xFF;
+    }
+  }
+//
+// Call routine to send mic buffer
+//
+  switch(protocol) {
+    case ORIGINAL_PROTOCOL:
+      old_protocol_process_local_mic(mic_buffer,1);
+      break;
+    case NEW_PROTOCOL:
+      new_protocol_process_local_mic(mic_buffer,1);
+      break;
+#ifdef RADIOBERRY
+    case RADIOBERRY_PROTOCOL:
+      radioberry_protocol_process_local_mic(mic_buffer,1);
+      break;
+#endif
+    default:
+      break;
+  }
+  return paContinue;
+}
+
+//
+// AUDIO_OPEN_OUTPUT
+//
+// open a PA stream for data from one of the RX
+//
+int audio_open_output(RECEIVER *rx)
+{
+  PaError err;
+  PaStreamParameters outputParameters;
+  long framesPerBuffer=(long) audio_buffer_size;
+
+  int padev = out_device_no[rx->audio_device];
+  fprintf(stderr,"audio_open_output: %d PADEV=%d\n",rx->audio_device,padev);
+  if(rx->audio_device<0 || rx->audio_device>=n_output_devices) {
+    rx->audio_device=-1;
+    return -1;
+  }
+  bzero( &outputParameters, sizeof( outputParameters ) ); //not necessary if you are filling in all the fields
+  outputParameters.channelCount = 1;   // Always MONO
+  outputParameters.device = padev;
+  outputParameters.hostApiSpecificStreamInfo = NULL;
+  outputParameters.sampleFormat = paFloat32;
+  outputParameters.suggestedLatency = Pa_GetDeviceInfo(padev)->defaultLowOutputLatency ;
+  outputParameters.hostApiSpecificStreamInfo = NULL; //See you specific host's API docs for info on using this field
+
+  // Try using AudioWrite without a call-back function
+
+  rx->playback_buffer=malloc(audio_buffer_size*sizeof(float));
+  rx->playback_offset=0;
+  err = Pa_OpenStream(&(rx->playback_handle), NULL, &outputParameters, 48000.0, framesPerBuffer, paNoFlag, NULL, NULL);
+  if (err != paNoError) {
+    fprintf(stderr,"PORTAUDIO ERROR: AOO open stream: %s\n",Pa_GetErrorText(err));
+    rx->playback_handle = NULL;
+    if (rx->playback_buffer) free(rx->playback_buffer);
+    rx->playback_buffer = NULL;
+    return -1;
+  }
+
+  err = Pa_StartStream(rx->playback_handle);
+  if (err != paNoError) {
+    fprintf(stderr,"PORTAUDIO ERROR: AOO start stream:%s\n",Pa_GetErrorText(err));
+    rx->playback_handle=NULL;
+    if (rx->playback_buffer) free(rx->playback_buffer);
+    rx->playback_buffer = NULL;
+    return -1;
+  }
+  // Write one buffer to avoid under-flow errors
+  // (this gives us 5 msec to pass before we have to call audio_write the first time)
+  bzero(rx->playback_buffer, (size_t) audio_buffer_size*sizeof(float));
+  err=Pa_WriteStream(rx->playback_handle, (void *) rx->playback_buffer, (unsigned long) audio_buffer_size);
+  return 0;
+}
+
+//
+// AUDIO_CLOSE_INPUT
+//
+// close a TX microphone stream
+//
+void audio_close_input()
+{
+  PaError err;
+
+  fprintf(stderr,"AudioCloseInput: %d\n", transmitter->input_device);
+
+  if(record_handle!=NULL) {
+    err = Pa_StopStream(record_handle);
+    if (err != paNoError) {
+      fprintf(stderr,"PORTAUDIO ERROR: ACI stop stream: %s\n",Pa_GetErrorText(err));
+    }
+    err = Pa_CloseStream(record_handle);
+    if (err != paNoError) {
+      fprintf(stderr,"PORTAUDIO ERROR: ACI close stream: %s\n",Pa_GetErrorText(err));
+    }
+    record_handle=NULL;
+  }
+  if(mic_buffer!=NULL) {
+    free(mic_buffer);
+    mic_buffer=NULL;
+  }
+}
+
+//
+// AUDIO_CLOSE_OUTPUT
+//
+// shut down the stream connected with audio from one of the RX
+//
+void audio_close_output(RECEIVER *rx) {
+  PaError err;
+
+  fprintf(stderr,"AudioCloseOutput: %d\n", rx->audio_device);
+
+// free the buffer first, this then indicates to audio_write to do nothing
+  if(rx->playback_buffer!=NULL) {
+    free(rx->playback_buffer);
+    rx->playback_buffer=NULL;
+  }
+
+  if(rx->playback_handle!=NULL) {
+    err = Pa_StopStream(rx->playback_handle);
+    if (err != paNoError) {
+      fprintf(stderr,"PORTAUDIO ERROR: ACO stop stream: %s\n",Pa_GetErrorText(err));
+    }
+    err = Pa_CloseStream(rx->playback_handle);
+    if (err != paNoError) {
+      fprintf(stderr,"PORTAUDIO ERROR: ACO close stream: %s\n",Pa_GetErrorText(err));
+    }
+    rx->playback_handle=NULL;
+  }
+}
+
+//
+// AUDIO_WRITE
+//
+// send RX audio data to a PA output stream
+// we have to store the data such that the PA callback function
+// can access it.
+//
+static int apt=0;
+int audio_write (RECEIVER *rx, short r, short l)
+{
+  PaError err;
+
+  if (rx->playback_handle != NULL && rx->playback_buffer != NULL) {
+    rx->playback_buffer[rx->playback_offset++] = (r + l) *0.000015259;  //   65536 --> 1.0   
+    if (rx->playback_offset == audio_buffer_size) {
+      rx->playback_offset=0;
+      err=Pa_WriteStream(rx->playback_handle, (void *) rx->playback_buffer, (unsigned long) audio_buffer_size);
+      //if (err != paNoError) {
+      //  fprintf(stderr,"PORTAUDIO ERROR: write stream dev=%d: %s\n",out_device_no[rx->audio_device],Pa_GetErrorText(err));
+      //  return -1;
+      // }
+    }
+  }
+  return 0;
+}
+
+//
+// CW audio write 
+// This is a dummy here because I think it is not correctly implemented in audio.c
+//
+void cw_audio_write(double sample) {
+}   
+
+#endif
diff --git a/radio.c b/radio.c
index 658c8f54ab5961fd8008d2a2712a3924d636b3be..512687b224a783eec7480f7921b007f30332e5a5 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -121,7 +121,11 @@ static gint save_timer_id;
 DISCOVERED *radio=NULL;
 
 char property_path[128];
+#ifdef __APPLE__
+sem_t *property_sem;
+#else
 sem_t property_sem;
+#endif
 
 RECEIVER *receiver[MAX_RECEIVERS];
 RECEIVER *active_receiver;
@@ -317,7 +321,8 @@ void reconfigure_radio() {
     } else {
       gtk_fixed_move(GTK_FIXED(fixed),sliders,0,y);
     }
-    gtk_widget_show_all(sliders);
+    gtk_widget_show_all(sliders);  // DL1YCF this shows both C25 and Alex ATT/Preamp sliders
+    att_type_changed();            // DL1YCF added here to hide the â€žwrong“ ones.
   } else {
     if(sliders!=NULL) {
       gtk_container_remove(GTK_CONTAINER(fixed),sliders); 
@@ -352,12 +357,21 @@ void start_radio() {
   gdk_window_set_cursor(gtk_widget_get_window(top_window),gdk_cursor_new(GDK_WATCH));
 
   int rc;
+#ifdef __APPLE__
+  property_sem=sem_open("PROPERTY", O_CREAT, 0700, 0);
+  rc=(property_sem == SEM_FAILED);
+#else
   rc=sem_init(&property_sem, 0, 0);
+#endif
   if(rc!=0) {
     fprintf(stderr,"start_radio: sem_init failed for property_sem: %d\n", rc);
     exit(-1);
   }
+#ifdef __APPLE__
+  sem_post(property_sem);
+#else
   sem_post(&property_sem);
+#endif
 
   char text[256];
   //for(i=0;i<devices;i++) {
@@ -1062,7 +1076,11 @@ void radioRestoreState() {
     char *value;
 
 fprintf(stderr,"radioRestoreState: %s\n",property_path);
+#ifdef __APPLE__
+    sem_wait(property_sem);
+#else
     sem_wait(&property_sem);
+#endif
     loadProperties(property_path);
 
     value=getProperty("region");
@@ -1264,14 +1282,22 @@ fprintf(stderr,"radioRestoreState: %s\n",property_path);
     value=getProperty("rx2_gain_slider");
        if(value) rx_gain_slider[1]=atoi(value);
        
+#ifdef __APPLE__
+    sem_post(property_sem);
+#else
     sem_post(&property_sem);
+#endif
 }
 
 void radioSaveState() {
     int i;
     char value[80];
 
+#ifdef __APPLE__
+    sem_wait(property_sem);
+#else
     sem_wait(&property_sem);
+#endif
     sprintf(value,"%d",region);
     setProperty("region",value);
     sprintf(value,"%d",buffer_size);
@@ -1457,7 +1483,11 @@ void radioSaveState() {
     setProperty("rigctl_port_base",value);
 
     saveProperties(property_path);
+#ifdef __APPLE__
+    sem_post(property_sem);
+#else
     sem_post(&property_sem);
+#endif
 }
 
 void calculate_display_average(RECEIVER *rx) {
index 2ea9f1deef38a6a53871d6706ae03eb251cf5a19..15c7f9c2bc25ed43ddd87f8243b7c340b967b1a5 100644 (file)
@@ -131,7 +131,8 @@ gboolean receiver_motion_notify_event(GtkWidget *widget, GdkEventMotion *event,
                                 &x,
                                 &y,
                                 &state);
-    if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) {
+    // DL1YCF added a pair of () to fix an error
+    if(((state & GDK_BUTTON1_MASK) == GDK_BUTTON1_MASK) || pressed) {
       int moved=last_x-x;
       vfo_move((long long)((float)moved*rx->hz_per_pixel));
       last_x=x;
index 3bd59c4dd732aba87e3de115b38578849980d84e..39bf084e1683160bdb01052e5d36d09b3f0fecd2 100644 (file)
 #define _RECEIVER_H
 
 #include <gtk/gtk.h>
+#ifdef PORTAUDIO
+#include "portaudio.h"
+#else
 #include <alsa/asoundlib.h>
+#endif
 
 #define AUDIO_BUFFER_SIZE 260
 
@@ -106,9 +110,14 @@ typedef struct _receiver {
   int local_audio;
   int mute_when_not_active;
   int audio_device;
+#ifdef PORTAUDIO
+  PaStream *playback_handle;
+  float *playback_buffer;
+#else
   snd_pcm_t *playback_handle;
-  int playback_offset;
   unsigned char *playback_buffer;
+#endif
+  int playback_offset;
   int low_latency;
 
   int squelch_enable;
index 6216fb3d238b3ad19ff416b2d3f84df866e3e5ef..c12139280f22b6e5bb5d9bd1b9f041329796314a 100644 (file)
--- a/rigctl.c
+++ b/rigctl.c
@@ -82,8 +82,9 @@ int connect_cnt = 0;
 
 int rigctlGetFilterLow();
 int rigctlGetFilterHigh();
-int rigctlSetFilterLow(int val);
-int rigctlSetFilterHigh(int val);
+// DL1YCF changed next to function to void
+void rigctlSetFilterLow(int val);
+void rigctlSetFilterHigh(int val);
 int new_level;
 int active_transmitter = 0;
 int rigctl_busy = 0;  // Used to tell rigctl_menu that launch has already occured
@@ -122,7 +123,8 @@ static int rigctl_timer = 0;
 
 typedef struct _client {
   int socket;
-  int address_length;
+  // Dl1YCF change from int to socklen_t
+  socklen_t address_length;
   struct sockaddr_in address;
   GThread *thread_id;
 } CLIENT;
@@ -197,6 +199,8 @@ static gpointer set_rigctl_timer (gpointer data) {
       // Wait throttle time
       usleep(RIGCTL_TIMER_DELAY);
       rigctl_timer = 0;
+      // DL1YCF added return statement to make compiler happy.
+      return NULL;
 }
 
 //
@@ -1930,16 +1934,16 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                     
                                                 if(agc_resp == 0) {
                                                    active_receiver->agc = AGC_OFF;
-                                                } else if(agc_resp >0 && agc_resp <= 5 || (agc_resp == 84)) {
+                                                } else if((agc_resp >0 && agc_resp <= 5) || (agc_resp == 84)) {       // DL1YCF: added () to improve readability
                                                    active_receiver->agc = AGC_FAST;
                                                   //  fprintf(stderr,"GT command FAST\n");
-                                                } else if(agc_resp >6 && agc_resp <= 10 || (agc_resp == 2*84)) {
+                                                } else if((agc_resp >6 && agc_resp <= 10) || (agc_resp == 2*84)) {    // DL1YCF: added () to improve readability
                                                    active_receiver->agc = AGC_MEDIUM;
                                                   // fprintf(stderr,"GT command MED\n");
-                                                } else if(agc_resp >11 && agc_resp <= 15 || (agc_resp == 3*84)) {
+                                                } else if((agc_resp >11 && agc_resp <= 15) || (agc_resp == 3*84)) {   // DL1YCF: added () to improve readability
                                                    active_receiver->agc = AGC_SLOW;
                                                    //fprintf(stderr,"GT command SLOW\n");
-                                                } else if(agc_resp >16 && agc_resp <= 20 || (agc_resp == 4*84)) {
+                                                } else if((agc_resp >16 && agc_resp <= 20) || (agc_resp == 4*84)) {   // DL1YCF: added () to improve readability
                                                    active_receiver->agc = AGC_LONG;
                                                    // fprintf(stderr,"GT command LONG\n");
                                                 }
@@ -2019,8 +2023,8 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                 send_resp(client_sock,"IS00000;");
                                              } 
                                           }  
-        else if((strcmp(cmd_str,"KS")==0) && (zzid_flag == 0) || 
-                (strcmp(cmd_str,"CS")==0) && (zzid_flag==1))  { 
+        else if(((strcmp(cmd_str,"KS")==0) && (zzid_flag == 0)) ||                               // Dl1YCF added () to improve readablity
+                ((strcmp(cmd_str,"CS")==0) && (zzid_flag==1)))  {                                // Dl1YCF added () to improve readablity
                                             // TS-2000 - KS - Set/Reads keying speed 0-060 max
                                             // PiHPSDR - ZZCS - Sets/Reads Keying speed
                                              if(len <=2) {
@@ -3053,8 +3057,8 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
                                                send_resp(client_sock,"?;"); 
                                              }
                                          }
-        else if((strcmp(cmd_str,"SD")==0) && (zzid_flag == 0) ||  
-                (strcmp(cmd_str,"CD")==0) && (zzid_flag ==1)) {  
+        else if(((strcmp(cmd_str,"SD")==0) && (zzid_flag == 0)) ||   // Dl1YCF added () to improve readablity
+                ((strcmp(cmd_str,"CD")==0) && (zzid_flag ==1))) {    // Dl1YCF added () to improve readablity
                                             // PiHPSDR - ZZCD - Set/Read CW Keyer Hang Time
                                             // TS-2000 - SD - Set/Read Break In Delay
                                             // 
@@ -3123,7 +3127,8 @@ void parse_cmd ( char * cmd_input,int len,int client_sock) {
 
                                             // Determine how high above 127 we are..making a range of 114 from S0 to S9+60db
                                             // 5 is a fugdge factor that shouldn't be there - but seems to get us to S9=SM015
-                                            level =  abs(127+(level + (double) adc_attenuation[receiver[r]->adc]))+5;
+                                           // DL1YCF replaced abs by fabs, and changed 127 to floating point constant
+                                            level =  fabs(127.0+(level + (double) adc_attenuation[receiver[r]->adc]))+5;
                                          
                                             // Clip the value just in case
                                             if(cmd_input[2] == '0') { 
@@ -3839,10 +3844,10 @@ int rigctlGetMode()  {
         }
 }
 
-
-int rigctlSetFilterLow(int val){
+// Changed these two functions to void
+void rigctlSetFilterLow(int val){
 };
-int rigctlSetFilterHigh(int val){
+void rigctlSetFilterHigh(int val){
 };
 
 void set_freqB(long long new_freqB) {      
index 704de4801d550c602ebc300b246428fc311bd3df..3e83bb166ae768d2483a4e548cd14fd7027c492e 100644 (file)
--- a/rx_menu.c
+++ b/rx_menu.c
@@ -113,12 +113,19 @@ static void mute_radio_cb(GtkWidget *widget, gpointer data) {
   active_receiver->mute_radio=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 }
 
+//
+// DL1YCF:
+// possible the device has been changed:
+// call audo_close_output with old device, audio_open_output with new one
+//
 static void local_output_changed_cb(GtkWidget *widget, gpointer data) {
-  active_receiver->audio_device=(int)(long)data;
-fprintf(stderr,"local_output_changed rx=%d to %d\n",active_receiver->id,active_receiver->audio_device);
+//active_receiver->audio_device=(int)(long)data;
+  int newdev = (int)(long)data;
+fprintf(stderr,"local_output_changed rx=%d from %d to %d\n",active_receiver->id,active_receiver->audio_device,newdev);
   if(active_receiver->local_audio) {
-    audio_close_output(active_receiver);
-    if(audio_open_output(active_receiver)==0) {
+    audio_close_output(active_receiver);                     // audio_close with OLD device
+    active_receiver->audio_device=newdev;                    // update rx to NEW device
+    if(audio_open_output(active_receiver)==0) {              // audio_open with NEW device
       active_receiver->local_audio=1;
     } else {
       active_receiver->local_audio=0;
index 19278846f202bfdd88489919a4bd3a97be280aeb..e3ceb7d5841c6436f0d8f941be8dd56622269c74 100644 (file)
 *
 */
 
+#ifdef __APPLE__
+
+
+//
+// MacOS has no vahi, but it does have libcurl.
+// Therefore we try to start the SDR app on the RedPitaya
+// assuming is has the (fixed) ip address which can be
+// read from $HOME/.rp.inet, if this does not succeed it
+// defaults to 192.168.1.3.
+//
+// So, on MacOS, just configure your STEMLAB/HAMLAB to this
+// fixed IP address and you need not open a browser to start
+// SDR *before* you can use piHPSDR.
+//
+// Sure it's not perfect, but it makes life much easier for me.
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <curl/curl.h>
+#include <glib.h>
+
+extern void status_text(const char *);
+
+static const char *appid = NULL;
+
+//
+// Extract the list of apps from the JSON answer
+//
+static size_t app_list_callback(void *buffer, size_t size, size_t nmemb, void *data) {
+  const gchar *needle;
+
+  needle="\"sdr_receiver_hpsdr\"";
+  if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
+    appid="sdr_receiver_hpsdr";
+  }
+
+  needle="\"sdr_transceiver_hpsdr\"";
+  if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
+    appid="sdr_transceiver_hpsdr";
+  }
+
+  needle="\"stemlab_sdr_transceiver_hpsdr\"";
+  if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
+    appid="stemlab_sdr_transceiver_hpsdr";
+  }
+
+  needle="\"hamlab_sdr_transceiver_hpsdr\"";
+  if (g_strstr_len(buffer, size*nmemb, needle) != NULL) {
+    appid="hamlab_sdr_transceiver_hpsdr";
+  }
+
+  if (appid) fprintf(stderr,"RedPitay WEB application to start: %s\n", appid);
+  return size * nmemb;
+}
+
+void stemlab_discovery() {
+  // this one is used "as the last resort", if nothing else is found.
+  size_t len;
+  char inet[20];
+  char txt[150];
+  CURL *curl_handle;
+  CURLcode curl_error;
+  FILE *fpin;
+  char *p;
+
+  fprintf(stderr,"Stripped-down STEMLAB/HAMLAB discovery...\n");
+//
+// Try to read inet addr from $HOME/.rp.inet, otherwise take 192.168.1.3
+//
+   strcpy(inet,"192,168.1.3");
+   p=getenv("HOME");
+   if (p) {
+     strncpy(txt,p, (size_t) 100);   // way less than size of txt
+   } else {
+     strcpy(txt,".");
+   }
+   strcat(txt,"/.rp.inet");
+   fprintf(stderr,"Trying to read inet addr from file=%s\n", txt);
+   fpin=fopen(txt, "r");
+   if (fpin) {
+     len=100;
+     p=txt;
+     len=getline(&p, &len, fpin);
+     // not txt now contains the trailing newline character
+     while (*p != 0) {
+       if (*p == '\n') *p = 0;
+       p++;
+     }
+     if (len < 20) strcpy(inet,txt);
+   }
+   fclose(fpin);
+   fprintf(stderr,"STEMLAB: using inet addr %s\n", inet);
+//
+// Do a HEAD request (poor curl's ping) to see whether the device is on-line
+// allow a 15 sec time-out
+  status_text("Looking for a STEMLAB web server ...");
+  curl_handle = curl_easy_init();
+  if (curl_handle == NULL) {
+    fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
+    return;
+  }
+  sprintf(txt,"http://%s",inet);
+  curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
+  curl_error = curl_easy_setopt(curl_handle, CURLOPT_NOBODY, (long) 1);
+  curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 15);
+  curl_error = curl_easy_perform(curl_handle);
+  curl_easy_cleanup(curl_handle);
+  if (curl_error ==  CURLE_OPERATION_TIMEDOUT) {
+    sprintf(txt,"No response from web server at %s", inet);
+    status_text(txt);
+    fprintf(stderr,"%s\n",txt);
+  }
+  if (curl_error != CURLE_OK) {
+    fprintf(stderr, "STEMLAB ping error: %s\n", curl_easy_strerror(curl_error));
+    return;
+  }
+  
+//
+//obtain a list of apps, and choose the right one by looking for the following
+//target strings (in that order). Whatever is found first, is started. Then, we rely
+//on the original discovery() to discover the device.
+//
+//hamlab_sdr_transceiver_hpsdr
+//stemlab_sdr_transceiver_hpsdr
+//sdr_transceiver_hpsdr
+//sdr_receiver_hpsdr
+//
+  curl_handle = curl_easy_init();
+  if (curl_handle == NULL) {
+    fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
+    return;
+  }
+  sprintf(txt,"http://%s/bazaar?apps=", inet);
+  curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
+  curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
+  curl_error = curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, app_list_callback);
+  curl_error = curl_easy_perform(curl_handle);
+  curl_easy_cleanup(curl_handle);
+  if (curl_error == CURLE_OPERATION_TIMEDOUT) {
+    status_text("No Response from RedPitaya in 60 secs");
+    fprintf(stderr,"60-sec TimeOut met when trying to get list of HPSDR apps from RedPitaya\n");
+  }
+  if (curl_error != CURLE_OK) {
+    fprintf(stderr, "STEMLAB app-list error: %s\n", curl_easy_strerror(curl_error));
+    return;
+  }
+    
+//
+// Now we actually start the hpsdr application
+// Actually, try to stop it first, then re-start it.
+//
+  if (appid) {
+    curl_handle = curl_easy_init();
+    if (curl_handle == NULL) {
+      fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
+      return;
+    }
+    sprintf(txt,"http://%s/bazaar?stop=%s",inet,appid);
+    curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
+    curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
+    curl_error = curl_easy_perform(curl_handle);
+    if (curl_error == CURLE_OPERATION_TIMEDOUT) {
+      fprintf(stderr,"60-sec TimeOut met when trying to stop HPSDR app on RedPitaya\n");
+    }
+    if (curl_error != CURLE_OK) {
+      fprintf(stderr, "STEMLAB app-start error: %s\n", curl_easy_strerror(curl_error));
+    }
+    curl_handle = curl_easy_init();
+    if (curl_handle == NULL) {
+      fprintf(stderr, "stemlab_start: Failed to create cURL handle\n");
+      return;
+    }
+    sprintf(txt,"http://%s/bazaar?start=%s",inet,appid);
+    curl_error = curl_easy_setopt(curl_handle, CURLOPT_URL, txt);
+    curl_error = curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (long) 60);
+    curl_error = curl_easy_perform(curl_handle);
+    if (curl_error == CURLE_OPERATION_TIMEDOUT) {
+      fprintf(stderr,"60-sec TimeOut met when trying to start HPSDR app on RedPitaya\n");
+    }
+    if (curl_error != CURLE_OK) {
+      fprintf(stderr, "STEMLAB app-start error: %s\n", curl_easy_strerror(curl_error));
+    }
+
+  }
+  // Whether or net we have successfully started the HPSDR application on the RedPitaya,
+  // we now return to the regular HPSDR protocol handling code that will eventually detect
+  // the "board". If this code does not work, you have to open a browser and start the HPSDR
+  // application manually.
+}
+
+// dummy function
+void stemlab_cleanup() {
+}
+
+// dummy function, never called
+void stemlab_start_app() {
+}
+
+#else
+
 #include <errno.h>
 #include <ifaddrs.h>
 #include <net/if.h>
@@ -324,3 +526,4 @@ void stemlab_cleanup(void) {
     curl_global_cleanup();
   }
 }
+#endif
index d1d0a873240e04ddb4432fc7eb158d666426520a..233a5b08e4de4f8bc405a5ac4365b41bf6cf5003 100644 (file)
@@ -52,6 +52,10 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 static gboolean step_select_cb (GtkWidget *widget, gpointer        data) {
   step=steps[(uintptr_t)data];
   vfo_update();
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void step_menu(GtkWidget *parent) {
index 80f38718b1bcab05531721af120b5e142b12686a..2bb38a91573d700bc0b74404aa5d012d7ad69379 100644 (file)
@@ -83,6 +83,10 @@ static gboolean store_select_cb (GtkWidget *widget, gpointer data) {
 
    // Save in the file now..
    memSaveState();
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static gboolean recall_select_cb (GtkWidget *widget, gpointer data) {
@@ -107,6 +111,10 @@ static gboolean recall_select_cb (GtkWidget *widget, gpointer data) {
     vfo_mode_changed(mem[index].mode);
     g_idle_add(ext_vfo_update,NULL);
 
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void store_menu(GtkWidget *parent) {
index d2c12ec4eb3eb54056980e01320b4be0cc2793b4..aeac25094036c7b9abc24035c963c9a08e31f72a 100644 (file)
@@ -63,6 +63,8 @@ static int waterfall_resample=8;
 
 int key = 0;
 
+// DL1YCF added next line.
+extern void cw_audio_write(double sample);
 static gint update_out_of_band(gpointer data) {
   TRANSMITTER *tx=(TRANSMITTER *)data;
   tx->out_of_band=0;
index a746fe181fe806b771dc219848800333e8772a79..7e08fc9993b681dd6712ce90fbf27dac96489532 100644 (file)
--- a/tx_menu.c
+++ b/tx_menu.c
@@ -160,6 +160,10 @@ static void local_input_changed_cb(GtkWidget *widget, gpointer data) {
 static gboolean emp_cb (GtkWidget *widget, gpointer data) {
   pre_emphasize=gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
   tx_set_pre_emphasize(transmitter,pre_emphasize);
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static void tune_value_changed_cb(GtkWidget *widget, gpointer data) {
index eaf6e8fa4bbb62fa5f824bf01edfa6c118052da2..43f6e5cc4ad865a1376905885760eeae21ed530c 100644 (file)
@@ -144,7 +144,8 @@ tx_panadapter_motion_notify_event_cb (GtkWidget      *widget,
                                 &x,
                                 &y,
                                 &state);
-  if((state & GDK_BUTTON1_MASK == GDK_BUTTON1_MASK) || pressed) {
+  // DL1YCF: added a pair of () to fix an error
+  if(((state & GDK_BUTTON1_MASK) == GDK_BUTTON1_MASK) || pressed) {
     int moved=last_x-x;
     vfo_move((long long)((float)moved*hz_per_pixel));
     last_x=x;
@@ -164,6 +165,10 @@ tx_panadapter_scroll_event_cb (GtkWidget      *widget,
   } else {
     vfo_move(-step);
   }
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 void tx_panadapter_update(TRANSMITTER *tx) {
diff --git a/vfo.c b/vfo.c
index 61262d8623b90ec5b676b5ac8b22458fc1dbf747..a279a3a4ef5be8f6f622d3cb87cb6742806b7086 100644 (file)
--- a/vfo.c
+++ b/vfo.c
@@ -513,6 +513,10 @@ vfo_scroll_event_cb (GtkWidget      *widget,
   } else {
     vfo_move(-step);
   }
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 
index e2356ea4b9d6a3fd1193d667c0bfb80ef248a5af..e47936d27128dc4427d728591b8b83ef5b288a2d 100644 (file)
@@ -161,6 +161,10 @@ static gboolean freqent_select_cb (GtkWidget *widget, gpointer data) {
     }
   }
   vfo_update();
+  // DL1YCF added return statement to make the compiler happy.
+  // however I am unsure about the correct return value.
+  // I would have coded this as a void function.
+  return FALSE;
 }
 
 static void rit_cb(GtkComboBox *widget,gpointer data) {
index 460ac435c51ee9c7b6f6d5932fef1679aa53caee..e14d5f2cbf73924be62803c22d6bc19c55cfe957 100644 (file)
@@ -91,6 +91,8 @@ static gpointer level_thread(gpointer arg) {
     g_idle_add(level_update,NULL);
     usleep(100000); // 100ms
   }
+  // DL1YCF added return statement to make compilers happy.
+  return NULL;
 }
 
 static void cleanup() {
index b673f8026b1a3496ca80cf043c81e4f5869e2f6e..bccebcc4e0846d79587c1987bc8ef766747162d0 100644 (file)
@@ -63,7 +63,8 @@ waterfall_configure_event_cb (GtkWidget         *widget,
   display_height=gtk_widget_get_allocated_height (widget);
   rx->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, display_width, display_height);
 
-  char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
+  // DL1YCF changed to uchar
+  unsigned char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
 
   memset(pixels, 0, display_width*display_height*3);
 
@@ -122,7 +123,8 @@ void waterfall_update(RECEIVER *rx) {
 
   float *samples;
   if(rx->pixbuf) {
-    char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
+    // DL1YCF changed to uchar
+    unsigned char *pixels = gdk_pixbuf_get_pixels (rx->pixbuf);
 
     int width=gdk_pixbuf_get_width(rx->pixbuf);
     int height=gdk_pixbuf_get_height(rx->pixbuf);
@@ -169,7 +171,8 @@ void waterfall_update(RECEIVER *rx) {
 
     float sample;
     int average=0;
-    char *p;
+    // DL1YCF changed to uchar
+    unsigned char *p;
     p=pixels;
     samples=rx->pixel_samples;
     for(i=0;i<width;i++) {