diff --git a/.gitignore b/.gitignore index 1eedf653a..b4d70d754 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ sdrangelove.supp .settings/ *.cs *.pro.user +.idea/* diff --git a/CMakeLists.txt b/CMakeLists.txt index a19d9c475..d33f4e5ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.1.0) cmake_policy(SET CMP0043 OLD) +# QT Framework +set(CMAKE_PREFIX_PATH "/Applications/Qt/5.7/clang_64/lib/cmake") + # use, i.e. don't skip the full RPATH for the build tree set(CMAKE_SKIP_BUILD_RPATH FALSE) @@ -56,6 +59,10 @@ IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|x86") SET(USE_SIMD "SSE2" CACHE STRING "Use SIMD instructions") ENDIF() +# MacOS Compatibility +if(APPLE) + find_package(ICONV) +endif(APPLE) ############################################################################## #include(${QT_USE_FILE}) diff --git a/apple_compat.c b/apple_compat.c new file mode 100644 index 000000000..1270ed284 --- /dev/null +++ b/apple_compat.c @@ -0,0 +1,77 @@ +/* + * APPLE Compatibility + */ + +#ifdef __APPLE__ + +#include +#include + +#include "apple_compat.h" + +int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) + { + errno = EINVAL; + return -1; + } + if(pthread_mutex_init(&barrier->mutex, 0) < 0) + { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) + { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->tripCount = count; + barrier->count = 0; + + return 0; +} + +int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->tripCount) + { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else + { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +/** + * Missing POSIX RealTime/Monotonic Clock + */ +#include + +int clock_gettime(int clk_id, struct timespec *t) { + mach_timebase_info_data_t timebase; + mach_timebase_info(&timebase); + uint64_t time; + time = mach_absolute_time(); + double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom); + double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9); + t->tv_sec = seconds; + t->tv_nsec = nseconds; + return 0; +} + +#endif // APPLE Compatibility \ No newline at end of file diff --git a/apple_compat.h b/apple_compat.h new file mode 100644 index 000000000..17feacfb2 --- /dev/null +++ b/apple_compat.h @@ -0,0 +1,45 @@ +/* + * APPLE Compatibility + */ + +#ifdef __APPLE__ + +/** + * Missing POSIX Thread Barriers implementation + */ +#ifndef PTHREAD_BARRIER_H_ +#define PTHREAD_BARRIER_H_ + +#include +#include + +typedef int pthread_barrierattr_t; +typedef struct +{ + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int tripCount; +} pthread_barrier_t; + + +int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count); + +int pthread_barrier_destroy(pthread_barrier_t *barrier); + +int pthread_barrier_wait(pthread_barrier_t *barrier); + +#endif // PTHREAD_BARRIER_H_ + +// +#ifndef CLOCK_REALTIME +# define CLOCK_REALTIME 0 +#endif + +#ifndef CLOCK_MONOTONIC +# define CLOCK_MONOTONIC 0 +#endif + +int clock_gettime(int clk_id, struct timespec *t); + +#endif // APPLE Compatibility \ No newline at end of file diff --git a/cmake/Modules/FindICONV.cmake b/cmake/Modules/FindICONV.cmake new file mode 100644 index 000000000..5d58070ef --- /dev/null +++ b/cmake/Modules/FindICONV.cmake @@ -0,0 +1,73 @@ +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) +include(CheckFunctionExists) +if (ICONV_INCLUDE_DIR) + # Already in cache, be silent + set(ICONV_FIND_QUIETLY TRUE) +endif() + +find_path(ICONV_INCLUDE_DIR iconv.h + /usr/include + /usr/local/include + /opt/local/include) + +set(POTENTIAL_ICONV_LIBS iconv libiconv libiconv2) + +find_library(ICONV_LIBRARY NAMES ${POTENTIAL_ICONV_LIBS} + PATHS /usr/lib /usr/local/lib /opt/local/lib) + +if(WIN32) + set(ICONV_DLL_NAMES iconv.dll libiconv.dll libiconv2.dll) + find_file(ICONV_DLL + NAMES ${ICONV_DLL_NAMES} + PATHS ENV PATH + NO_DEFAULT_PATH) + find_file(ICONV_DLL_HELP + NAMES ${ICONV_DLL_NAMES} + PATHS ENV PATH + ${ICONV_INCLUDE_DIR}/../bin) + if(ICONV_FIND_REQUIRED) + if(NOT ICONV_DLL AND NOT ICONV_DLL_HELP) + message(FATAL_ERROR "Could not find iconv.dll, please add correct your PATH environment variable") + endif() + if(NOT ICONV_DLL AND ICONV_DLL_HELP) + get_filename_component(ICONV_DLL_HELP ${ICONV_DLL_HELP} PATH) + message(STATUS) + message(STATUS "Could not find iconv.dll in standard search path, please add ") + message(STATUS "${ICONV_DLL_HELP}") + message(STATUS "to your PATH environment variable.") + message(STATUS) + message(FATAL_ERROR "exit cmake") + endif() + endif() + if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY AND ICONV_DLL) + set(ICONV_FOUND TRUE) + endif() +else() + check_function_exists(iconv HAVE_ICONV_IN_LIBC) + if(ICONV_INCLUDE_DIR AND HAVE_ICONV_IN_LIBC) + set(ICONV_FOUND TRUE) + set(ICONV_LIBRARY CACHE TYPE STRING FORCE) + endif() + if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY) + set(ICONV_FOUND TRUE) + endif() +endif() + + + +if(ICONV_FOUND) + if(NOT ICONV_FIND_QUIETLY) + message(STATUS "Found iconv library: ${ICONV_LIBRARY}") + #message(STATUS "Found iconv dll : ${ICONV_DLL}") + endif() +else() + if(ICONV_FIND_REQUIRED) + message(STATUS "Looked for iconv library named ${POTENTIAL_ICONV_LIBS}.") + message(STATUS "Found no acceptable iconv library. This is fatal.") + message(STATUS "iconv header: ${ICONV_INCLUDE_DIR}") + message(STATUS "iconv lib : ${ICONV_LIBRARY}") + message(FATAL_ERROR "Could NOT find iconv library") + endif() +endif() + +mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR) \ No newline at end of file diff --git a/fcdhid/CMakeLists.txt b/fcdhid/CMakeLists.txt index f90316c9b..df44433ac 100644 --- a/fcdhid/CMakeLists.txt +++ b/fcdhid/CMakeLists.txt @@ -1,11 +1,13 @@ project(fcdhid) set(fcdhid_SOURCES + ../apple_compat.c hid-libusb.c fcdhid.c ) set(fcdhid_HEADERS + ../apple_compat.h fcdhid.h hid-libusb.h hidapi.h @@ -25,6 +27,7 @@ add_library(fcdhid SHARED target_link_libraries(fcdhid ${LIBUSB_LIBRARIES} + ${ICONV_LIBRARY} ) -install(TARGETS fcdhid DESTINATION lib) \ No newline at end of file +install(TARGETS fcdhid DESTINATION lib) diff --git a/fcdhid/hid-libusb.c b/fcdhid/hid-libusb.c index af11e6a80..fbed9bd4b 100644 --- a/fcdhid/hid-libusb.c +++ b/fcdhid/hid-libusb.c @@ -65,6 +65,15 @@ extern "C" { #define DETACH_KERNEL_DRIVER #endif +/** + * MacOS does not implement POSIX Thread Barriers + */ +#ifdef __APPLE__ + +#include "../apple_compat.h" + +#endif + /* Uncomment to enable the retrieval of Usage and Usage Page in hid_enumerate(). Warning, on platforms different from FreeBSD this is very invasive as it requires the detach diff --git a/plugins/channel/demodbfm/CMakeLists.txt b/plugins/channel/demodbfm/CMakeLists.txt index 09899dc17..d509a8321 100644 --- a/plugins/channel/demodbfm/CMakeLists.txt +++ b/plugins/channel/demodbfm/CMakeLists.txt @@ -49,4 +49,4 @@ target_link_libraries(demodbfm qt5_use_modules(demodbfm Core Widgets OpenGL Multimedia) -install(TARGETS demodbfm DESTINATION lib/plugins/channel) \ No newline at end of file +install(TARGETS demodbfm DESTINATION lib/plugins/channel) diff --git a/plugins/channel/demodbfm/rdsparser.cpp b/plugins/channel/demodbfm/rdsparser.cpp index 89af931de..54c7705f6 100644 --- a/plugins/channel/demodbfm/rdsparser.cpp +++ b/plugins/channel/demodbfm/rdsparser.cpp @@ -526,15 +526,21 @@ void RDSParser::decode_type0(unsigned int *group, bool B) if (af_1) { - std::pair, bool> res = m_g0_alt_freq.insert(af_1/1e3); - m_g0_af_updated = m_g0_af_updated || res.second; + // @TODO: Find proper header or STL on OSX +#ifndef __APPLE__ + std::pair, bool> res = m_g0_alt_freq.insert(af_1/1e3); + m_g0_af_updated = m_g0_af_updated || res.second; +#endif no_af += 1; } if (af_2) { - std::pair, bool> res = m_g0_alt_freq.insert(af_2/1e3); - m_g0_af_updated = m_g0_af_updated || res.second; + // @TODO: Find proper header or STL on OSX +#ifndef __APPLE__ + std::pair, bool> res = m_g0_alt_freq.insert(af_2/1e3); + m_g0_af_updated = m_g0_af_updated || res.second; +#endif no_af += 2; } diff --git a/plugins/samplesource/hackrf/CMakeLists.txt b/plugins/samplesource/hackrf/CMakeLists.txt index bcc4ca783..bc47b71db 100644 --- a/plugins/samplesource/hackrf/CMakeLists.txt +++ b/plugins/samplesource/hackrf/CMakeLists.txt @@ -21,7 +21,7 @@ set(hackrf_FORMS ) include_directories( - . + . ${CMAKE_CURRENT_BINARY_DIR} ${LIBHACKRF_INCLUDE_DIR} ) diff --git a/sdrangel.macos.pro b/sdrangel.macos.pro new file mode 100644 index 000000000..d711c86c0 --- /dev/null +++ b/sdrangel.macos.pro @@ -0,0 +1,30 @@ +#-------------------------------------------------------- +# +# Pro file for MacOS builds with Qt Creator +# +#-------------------------------------------------------- + +TEMPLATE = subdirs +SUBDIRS = sdrbase +SUBDIRS += lz4 +SUBDIRS += librtlsdr +SUBDIRS += libhackrf +SUBDIRS += libairspy +SUBDIRS += plugins/samplesource/filesource +SUBDIRS += plugins/samplesource/sdrdaemon +SUBDIRS += plugins/samplesource/rtlsdr +SUBDIRS += plugins/samplesource/hackrf +SUBDIRS += plugins/samplesource/airspy +SUBDIRS += plugins/channel/chanalyzer +SUBDIRS += plugins/channel/demodam +SUBDIRS += plugins/channel/demodbfm +SUBDIRS += plugins/channel/demodlora +SUBDIRS += plugins/channel/demodnfm +SUBDIRS += plugins/channel/demodssb +SUBDIRS += plugins/channel/demodwfm +SUBDIRS += plugins/channel/tcpsrc +SUBDIRS += plugins/channel/udpsrc + +# Main app must be last +CONFIG += ordered +SUBDIRS += app diff --git a/sdrbase/audio/audiooutput.cpp b/sdrbase/audio/audiooutput.cpp index ce435f068..13bb3d97f 100644 --- a/sdrbase/audio/audiooutput.cpp +++ b/sdrbase/audio/audiooutput.cpp @@ -150,8 +150,12 @@ bool AudioOutput::open(OpenMode mode) qint64 AudioOutput::readData(char* data, qint64 maxLen) { - //qDebug("AudioOutput::readData: %lld", maxLen); - QMutexLocker mutexLocker(&m_mutex); + //qDebug("AudioOutput::readData: %lld", maxLen); + + // @TODO: Study this mutex on OSX, for now deadlocks possible +#ifndef __APPLE__ + QMutexLocker mutexLocker(&m_mutex); +#endif unsigned int framesPerBuffer = maxLen / 4; @@ -183,7 +187,7 @@ qint64 AudioOutput::readData(char* data, qint64 maxLen) if (samples != framesPerBuffer) { - //qDebug("AudioOutput::readData: read %d samples vs %d requested", samples, framesPerBuffer); + qDebug("AudioOutput::readData: read %d samples vs %d requested", samples, framesPerBuffer); } for (uint i = 0; i < samples; i++) @@ -195,8 +199,7 @@ qint64 AudioOutput::readData(char* data, qint64 maxLen) ++src; ++dst; } - } - + } // convert to int16 //std::vector::const_iterator src = m_mixBuffer.begin(); // Valgrind optim diff --git a/sdrbase/dsp/phaselock.cpp b/sdrbase/dsp/phaselock.cpp index 173e7c8f8..8c214f71c 100644 --- a/sdrbase/dsp/phaselock.cpp +++ b/sdrbase/dsp/phaselock.cpp @@ -182,7 +182,7 @@ void PhaseLock::process(const std::vector& samples_in, std::vector& // Convert I/Q ratio to estimate of phase error. Real phase_err; - if (phasor_i > abs(phasor_q)) { + if (phasor_i > std::abs(phasor_q)) { // We are within +/- 45 degrees from lock. // Use simple linear approximation of arctan. phase_err = phasor_q / phasor_i; @@ -278,7 +278,7 @@ void PhaseLock::process(const Real& sample_in, Real *samples_out) // Convert I/Q ratio to estimate of phase error. Real phase_err; - if (phasor_i > abs(phasor_q)) { + if (phasor_i > std::abs(phasor_q)) { // We are within +/- 45 degrees from lock. // Use simple linear approximation of arctan. phase_err = phasor_q / phasor_i; diff --git a/sdrbase/gui/aboutdialog.ui b/sdrbase/gui/aboutdialog.ui index ea6b7c795..85c699ae5 100644 --- a/sdrbase/gui/aboutdialog.ui +++ b/sdrbase/gui/aboutdialog.ui @@ -84,7 +84,7 @@ - <html><head/><body><p>Version 2.0.0 - Copyright (C) 2015-2016 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a> This is a complete redesign from RTL-SDRangelove at <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/hexameron/rtl-sdrangelove</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in RTL-SDRangelove</p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> + <html><head/><body><p>Version 2.0.1 - Copyright (C) 2015-2016 Edouard Griffiths, F4EXB. </p><p>Code at <a href="https://github.com/f4exb/sdrangel"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/f4exb/sdrangel</span></a> This is a complete redesign from RTL-SDRangelove at <a href="https://github.com/hexameron/rtl-sdrangelove"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/hexameron/rtl-sdrangelove</span></a></p><p>Many thanks to the original developers:</p><p>The osmocom developer team - especially horizon, Hoernchen &amp; tnt.</p><p>Christian Daniel from maintech GmbH.</p><p>John Greb (hexameron) for the contributions in RTL-SDRangelove</p><p>The following rules apply to the SDRangel main application and libsdrbase:<br/>This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of the GNU General Public License along with this program. If not, see <a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses/</span></a>.</p><p>For the license of installed plugins, look into the plugin list.</p></body></html> true diff --git a/sdrbase/mainwindow.cpp b/sdrbase/mainwindow.cpp index 0f5513382..0131e30f3 100644 --- a/sdrbase/mainwindow.cpp +++ b/sdrbase/mainwindow.cpp @@ -333,7 +333,7 @@ void MainWindow::savePresetSettings(Preset* preset, int tabIndex) void MainWindow::createStatusBar() { QString qtVersionStr = QString("Qt %1 ").arg(QT_VERSION_STR); - m_showSystemWidget = new QLabel("SDRangel v2.0.0 " + qtVersionStr + QSysInfo::prettyProductName(), this); + m_showSystemWidget = new QLabel("SDRangel v2.0.1 " + qtVersionStr + QSysInfo::prettyProductName(), this); statusBar()->addPermanentWidget(m_showSystemWidget); m_dateTimeWidget = new QLabel(tr("Date"), this); diff --git a/sdrbase/plugin/pluginmanager.cpp b/sdrbase/plugin/pluginmanager.cpp index 13dcf8b02..fc4e68126 100644 --- a/sdrbase/plugin/pluginmanager.cpp +++ b/sdrbase/plugin/pluginmanager.cpp @@ -382,7 +382,7 @@ void PluginManager::loadPlugins(const QDir& dir) foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { - if (fileName.endsWith(".so") || fileName.endsWith(".dll")) + if (fileName.endsWith(".so") || fileName.endsWith(".dll") || fileName.endsWith(".dylib")) { qDebug() << "PluginManager::loadPlugins: fileName: " << qPrintable(fileName);