Skip to content

Commit

Permalink
Port to MacOS, Compiler warnings removed, thus found many errors.
Browse files Browse the repository at this point in the history
Includes two fixes for STEMlab/HAMlab.
  • Loading branch information
dl1ycf committed Jun 8, 2018
1 parent 0fedd7b commit 0b0d1ad
Show file tree
Hide file tree
Showing 43 changed files with 1,389 additions and 75 deletions.
16 changes: 16 additions & 0 deletions MacOS/Info.plist
Original file line number Diff line number Diff line change
@@ -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>
1 change: 1 addition & 0 deletions MacOS/PkgInfo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
APPLpihp
Binary file added MacOS/hpsdr.icns
Binary file not shown.
Binary file added MacOS/hpsdr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions MacOS/pihpsdr.sh
Original file line number Diff line number Diff line change
@@ -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
101 changes: 95 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -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` \
Expand All @@ -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)
Expand Down Expand Up @@ -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 \
Expand Down Expand Up @@ -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)

Expand All @@ -411,6 +457,7 @@ prebuild:
clean:
-rm -f *.o
-rm -f $(PROGRAM)
-rm -rf $(PROGRAM).app

install: $(PROGRAM)
cp $(PROGRAM) /usr/local/bin
Expand All @@ -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
#############################################################################

141 changes: 141 additions & 0 deletions README.MacOS
Original file line number Diff line number Diff line change
@@ -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.

4 changes: 4 additions & 0 deletions agc_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 7 additions & 1 deletion audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
*
*/

//
// 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>

Expand Down Expand Up @@ -527,4 +532,5 @@ fprintf(stderr,"output_device: %s\n",device_id);
n++;
}
snd_device_name_free_hint(hints);
}
}
#endif
Loading

0 comments on commit 0b0d1ad

Please sign in to comment.