2024-01-27 20:16:14 +01:00
#
/*
* Copyright ( C ) 2015 , 2023
* Jan van Katwijk ( J . vanKatwijk @ gmail . com )
* Lazy Chair Computing
*
* This file is part of the Qt - DAB
*
* Qt - DAB 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 .
*
* Qt - DAB 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 . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Qt - DAB ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <QCoreApplication>
# include <QSettings>
# include <QMessageBox>
# include <QDebug>
# include <QDateTime>
# include <QFile>
# include <QStringList>
# include <QMouseEvent>
# include <QDir>
2024-02-06 15:37:07 +01:00
# include <QColorDialog>
2024-01-27 20:16:14 +01:00
# include <fstream>
# include "dab-constants.h"
# include "mot-content-types.h"
# include <iostream>
# include <numeric>
# include <vector>
# include "radio.h"
2024-02-16 15:46:54 +01:00
# include "config-handler.h"
2024-01-27 20:16:14 +01:00
# include "ofdm-handler.h"
# include "schedule-selector.h"
# include "element-selector.h"
# include "dab-tables.h"
# include "dab-params.h"
# include "ITU_Region_1.h"
# include "coordinates.h"
# include "mapport.h"
# include "techdata.h"
# include "aboutdialog.h"
2024-02-25 14:18:27 +01:00
# include "db-loader.h"
# include "cacheElement.h"
# include "distances.h"
2024-03-04 14:45:33 +01:00
# include "position-handler.h"
2024-01-27 20:16:14 +01:00
# ifdef TCP_STREAMER
# include "tcp-streamer.h"
# else
2024-03-13 19:45:53 +01:00
# include "Qt-audio.h"
2024-01-27 20:16:14 +01:00
# include "audiosink.h"
# endif
# include "time-table.h"
# include "device-exceptions.h"
2024-02-25 14:18:27 +01:00
# include "settingNames.h"
2024-03-13 19:45:53 +01:00
# include "uploader.h"
2024-01-27 20:16:14 +01:00
2024-03-13 19:45:53 +01:00
# if defined (__MINGW32__) || defined (_WIN32)
2024-01-27 20:16:14 +01:00
# include <windows.h>
__int64 FileTimeToInt64 ( FILETIME & ft ) {
ULARGE_INTEGER foo ;
foo . LowPart = ft . dwLowDateTime ;
foo . HighPart = ft . dwHighDateTime ;
return ( foo . QuadPart ) ;
}
bool get_cpu_times ( size_t & idle_time , size_t & total_time ) {
FILETIME IdleTime , KernelTime , UserTime ;
size_t thisIdle , thisKernel , thisUser ;
GetSystemTimes ( & IdleTime , & KernelTime , & UserTime ) ;
thisIdle = FileTimeToInt64 ( IdleTime ) ;
thisKernel = FileTimeToInt64 ( KernelTime ) ;
thisUser = FileTimeToInt64 ( UserTime ) ;
idle_time = ( size_t ) thisIdle ;
total_time = ( size_t ) ( thisKernel + thisUser ) ;
return true ;
}
# else
std : : vector < size_t > get_cpu_times ( ) {
std : : ifstream proc_stat ( " /proc/stat " ) ;
proc_stat . ignore ( 5 , ' ' ) ; // Skip the 'cpu' prefix.
std : : vector < size_t > times ;
for ( size_t time ; proc_stat > > time ; times . push_back ( time ) ) ;
return times ;
}
bool get_cpu_times ( size_t & idle_time , size_t & total_time ) {
const std : : vector < size_t > cpu_times = get_cpu_times ( ) ;
if ( cpu_times . size ( ) < 4 )
return false ;
idle_time = cpu_times [ 3 ] ;
total_time = std : : accumulate ( cpu_times . begin ( ) ,
cpu_times . end ( ) , ( size_t ) 0 ) ;
return true ;
}
2024-03-13 19:45:53 +01:00
# include <unistd.h>
# endif
2024-04-03 18:44:52 +02:00
static inline
QString ids_to_string ( int mainId , int subId ) {
2024-04-10 19:49:55 +02:00
return " ( " + QString : : number ( mainId ) + " - "
2024-04-03 18:44:52 +02:00
+ QString : : number ( subId ) + " ) " ;
}
2024-03-13 19:45:53 +01:00
static inline
QStringList splitter ( const QString & s ) {
# if QT_VERSION >= QT_VERSION_CHECK (5, 15, 2)
QStringList list = s . split ( " : " , Qt : : SkipEmptyParts ) ;
# else
QStringList list = s . split ( " : " , QString : : SkipEmptyParts ) ;
2024-01-27 20:16:14 +01:00
# endif
2024-03-13 19:45:53 +01:00
return list ;
}
2024-01-27 20:16:14 +01:00
static const
2024-02-06 15:37:07 +01:00
char LABEL_STYLE [ ] = " color:lightgreen " ;
2024-01-27 20:16:14 +01:00
RadioInterface : : RadioInterface ( QSettings * Si ,
const QString & scanListFile ,
const QString & presetFile ,
const QString & freqExtension ,
const QString & schedule ,
bool error_report ,
int32_t dataPort ,
int32_t clockPort ,
int fmFrequency ,
QWidget * parent ) :
QWidget ( parent ) ,
2024-06-01 11:12:04 +02:00
theSpectrumBuffer ( 16 * 32768 ) ,
theIQBuffer ( 2 * 1536 ) ,
theTIIBuffer ( 32768 ) ,
theNULLBuffer ( 32768 ) ,
theChannelBuffer ( 4096 ) ,
theSNRBuffer ( 512 ) ,
theResponseBuffer ( 32768 ) ,
theFrameBuffer ( 2 * 32768 ) ,
theDataBuffer ( 32768 ) ,
theAudioBuffer ( 8 * 32768 ) ,
2024-01-27 20:16:14 +01:00
stdDevBuffer ( 2 * 1536 ) ,
2024-06-01 11:12:04 +02:00
theNewDisplay ( this , Si ) ,
theSNRViewer ( this , Si ) ,
theDLCache ( 10 ) ,
theTIIProcessor ( Si ) ,
theFilenameFinder ( Si ) ,
2024-01-27 20:16:14 +01:00
theScheduler ( this , schedule ) ,
theTechData ( 16 * 32768 ) ,
2024-06-01 11:12:04 +02:00
theAudioConverter ( this ) ,
theScanlistHandler ( this ,
2024-01-27 20:16:14 +01:00
scanListFile ) ,
2024-06-01 11:12:04 +02:00
theDeviceChoser ( Si ) ,
theDXDisplay ( this , Si ) ,
2024-10-14 15:35:13 +02:00
theLogger ( Si ) ,
2024-06-01 11:12:04 +02:00
theSCANHandler ( this , Si , freqExtension ) {
2024-01-27 20:16:14 +01:00
int16_t k ;
QString h ;
dabSettings_p = Si ;
this - > error_report = error_report ;
this - > fmFrequency = fmFrequency ;
this - > dlTextFile = nullptr ;
this - > ficDumpPointer = nullptr ;
this - > the_aboutLabel = nullptr ;
running . store ( false ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler = nullptr ;
2024-01-27 20:16:14 +01:00
stereoSetting = false ;
maxDistance = - 1 ;
contentTable_p = nullptr ;
scanTable_p = nullptr ;
mapHandler = nullptr ;
2024-06-01 11:12:04 +02:00
theDXDisplay . hide ( ) ;
2024-01-27 20:16:14 +01:00
// "globals" is introduced to reduce the number of parameters
// for the ofdmHandler
2024-06-01 11:12:04 +02:00
globals . spectrumBuffer = & theSpectrumBuffer ;
globals . iqBuffer = & theIQBuffer ;
globals . responseBuffer = & theResponseBuffer ;
globals . tiiBuffer = & theTIIBuffer ;
globals . nullBuffer = & theNULLBuffer ;
globals . channelBuffer = & theChannelBuffer ;
globals . snrBuffer = & theSNRBuffer ;
globals . frameBuffer = & theFrameBuffer ;
2024-01-27 20:16:14 +01:00
globals . stdDevBuffer = & stdDevBuffer ;
globals . dabMode =
2024-03-04 14:45:33 +01:00
dabSettings_p - > value ( " dabMode " , 1 ) . toInt ( ) ;
2024-01-27 20:16:14 +01:00
globals . threshold =
dabSettings_p - > value ( " threshold " , 3 ) . toInt ( ) ;
globals . diff_length =
dabSettings_p - > value ( " diff_length " , DIFF_LENGTH ) . toInt ( ) ;
globals . tii_delay =
dabSettings_p - > value ( " tii_delay " , 5 ) . toInt ( ) ;
if ( globals . tii_delay < 2 )
globals . tii_delay = 2 ;
globals . tii_depth =
dabSettings_p - > value ( " tii_depth " , 4 ) . toInt ( ) ;
globals . echo_depth =
dabSettings_p - > value ( " echo_depth " , 1 ) . toInt ( ) ;
# ifdef _SEND_DATAGRAM_
ipAddress = dabSettings_p - > value ( " ipAddress " , " 127.0.0.1 " ) . toString ( ) ;
port = dabSettings_p - > value ( " port " , 8888 ) . toInt ( ) ;
# endif
// set on top or not? checked at start up
2024-02-25 14:18:27 +01:00
if ( int_configValue ( " onTop " , 0 ) = = 1 )
2024-01-27 20:16:14 +01:00
setWindowFlags ( windowFlags ( ) | Qt : : WindowStaysOnTopHint ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
QPixmap p ;
QString labelName =
QString ( " :res/signal%1.png " ) . arg ( i , 1 , 10 , QChar ( ' 0 ' ) ) ;
p . load ( labelName , " png " ) ;
strengthLabels . push_back ( p ) ;
}
// The settings are done, now creation of the GUI parts
setupUi ( this ) ;
// and init the up and down button
{ QPixmap p ;
if ( p . load ( " :res/up-arrow.png " , " png " ) )
prevChannelButton - > setPixmap ( p . scaled ( 30 , 30 , Qt : : KeepAspectRatio ) ) ;
if ( p . load ( " :res/down-arrow.png " , " png " ) )
nextChannelButton - > setPixmap ( p . scaled ( 30 , 30 , Qt : : KeepAspectRatio ) ) ;
if ( p . load ( " :res/details24.png " , " png " ) )
serviceButton - > setPixmap ( p . scaled ( 30 , 30 , Qt : : KeepAspectRatio ) ) ;
else
2024-01-29 15:47:49 +01:00
fprintf ( stderr , " Loading details button failed \n " ) ;
2024-10-14 15:35:13 +02:00
if ( p . load ( " :res/folder_button.png " , " png " ) )
folder_shower - > setPixmap ( p . scaled ( 30 , 30 , Qt : : KeepAspectRatio ) ) ;
2024-01-27 20:16:14 +01:00
}
2024-03-13 19:45:53 +01:00
2024-10-14 15:35:13 +02:00
connect ( folder_shower , SIGNAL ( clicked ( ) ) ,
this , SLOT ( handle_folderButton ( ) ) ) ;
2024-03-13 19:45:53 +01:00
// put the widgets in the right place and create the workers
2024-04-15 14:03:12 +02:00
set_position_and_size ( dabSettings_p , this , S_MAIN_WIDGET ) ;
2024-02-16 15:46:54 +01:00
configHandler_p = new configHandler ( this , dabSettings_p ) ;
2024-01-27 20:16:14 +01:00
the_ensembleHandler = new ensembleHandler ( this , dabSettings_p ,
presetFile ) ;
2024-02-16 15:46:54 +01:00
// we have the configuration handler and the ensemble handler,
// connect some signals directly
configHandler_p - > set_connections ( ) ;
2024-06-01 11:12:04 +02:00
configHandler_p - > setDeviceList ( theDeviceChoser .
2024-03-30 19:39:33 +01:00
getDeviceList ( ) ) ;
2024-04-10 19:49:55 +02:00
connect ( configHandler_p , & configHandler : : frameClosed ,
this , & RadioInterface : : handle_configFrame_closed ) ;
connect ( configHandler_p , & configHandler : : handle_fontSelect ,
the_ensembleHandler , & ensembleHandler : : handle_fontSelect ) ;
connect ( configHandler_p , & configHandler : : handle_fontSizeSelect ,
the_ensembleHandler , & ensembleHandler : : handle_fontSizeSelect ) ;
connect ( configHandler_p , & configHandler : : handle_fontColorSelect ,
the_ensembleHandler , & ensembleHandler : : handle_fontColorSelect ) ;
connect ( configHandler_p , & configHandler : : set_serviceOrder ,
the_ensembleHandler , & ensembleHandler : : set_serviceOrder ) ;
2024-06-01 11:12:04 +02:00
connect ( & theNewDisplay , & displayWidget : : frameClosed ,
2024-04-10 19:49:55 +02:00
this , & RadioInterface : : handle_newDisplayFrame_closed ) ;
2024-01-27 20:16:14 +01:00
# ifdef HAVE_RTLSDR_V3
2024-03-04 14:45:33 +01:00
SystemVersion = QString ( " X " ) + " with RTLSDR-V3 " ;
2024-01-27 20:16:14 +01:00
# elif HAVE_RTLSDR_V4
2024-03-04 14:45:33 +01:00
SystemVersion = QString ( " X " ) + " with RTLSDR-V4 " ;
2024-01-27 20:16:14 +01:00
# else
2024-03-04 14:45:33 +01:00
SystemVersion = QString ( " X " ) ;
2024-01-27 20:16:14 +01:00
# endif
setWindowTitle ( " Qt-DAB-6. " + SystemVersion ) ;
ensembleWidget - > setWidget ( the_ensembleHandler ) ;
2024-03-04 14:45:33 +01:00
connect ( the_ensembleHandler ,
2024-04-10 19:49:55 +02:00
& ensembleHandler : : selectService ,
this , & RadioInterface : : localSelect_SS ) ;
2024-01-27 20:16:14 +01:00
connect ( the_ensembleHandler ,
2024-04-10 19:49:55 +02:00
& ensembleHandler : : start_background_task ,
this , & RadioInterface : : start_background_task ) ;
2024-01-27 20:16:14 +01:00
techWindow_p = new techData ( this , dabSettings_p , & theTechData ) ;
2024-04-10 19:49:55 +02:00
connect ( techWindow_p , & techData : : frameClosed ,
this , & RadioInterface : : handle_techFrame_closed ) ;
2024-02-25 14:18:27 +01:00
if ( dabSettings_p - > value ( NEW_DISPLAY_VISIBLE , 0 ) . toInt ( ) ! = 0 )
2024-06-01 11:12:04 +02:00
theNewDisplay . show ( ) ;
2024-01-27 20:16:14 +01:00
else
2024-06-01 11:12:04 +02:00
theNewDisplay . hide ( ) ;
2024-01-27 20:16:14 +01:00
2024-02-25 14:18:27 +01:00
labelStyle = dabSettings_p - > value ( LABEL_COLOR ,
2024-02-06 15:37:07 +01:00
LABEL_STYLE ) . toString ( ) ;
2024-03-04 14:45:33 +01:00
QFont font = serviceLabel - > font ( ) ;
font . setPointSize ( 16 ) ;
font . setBold ( true ) ;
serviceLabel - > setStyleSheet ( labelStyle ) ;
serviceLabel - > setFont ( font ) ;
programTypeLabel - > setStyleSheet ( labelStyle ) ;
2024-03-13 19:45:53 +01:00
font = ensembleId - > font ( ) ;
font . setPointSize ( 14 ) ;
ensembleId - > setFont ( font ) ;
2024-03-04 14:45:33 +01:00
2024-02-16 15:46:54 +01:00
nextService . valid = false ;
2024-01-27 20:16:14 +01:00
channel . currentService . valid = false ;
channel . serviceCount = - 1 ;
channel . targetPos = position { 0 , 0 } ;
2024-02-16 15:46:54 +01:00
localPos . latitude =
2024-02-25 14:18:27 +01:00
dabSettings_p - > value ( HOME_LATITUDE , 0 ) . toFloat ( ) ;
2024-02-16 15:46:54 +01:00
localPos . longitude =
2024-02-25 14:18:27 +01:00
dabSettings_p - > value ( HOME_LONGITUDE , 0 ) . toFloat ( ) ;
2024-01-27 20:16:14 +01:00
techWindow_p - > hide ( ) ; // until shown otherwise
stillMuting - > hide ( ) ;
2024-03-13 19:45:53 +01:00
2024-01-27 20:16:14 +01:00
# ifdef DATA_STREAMER
dataStreamer_p = new tcpServer ( dataPort ) ;
# else
( void ) dataPort ;
# endif
# ifdef CLOCK_STREAMER
clockStreamer_p = new tcpServer ( clockPort ) ;
# else
( void ) clockPort ;
# endif
2024-10-09 17:57:23 +02:00
volumeSlider - > hide ( ) ;
2024-01-27 20:16:14 +01:00
// Where do we leave the audio out?
2024-02-16 15:46:54 +01:00
configHandler_p - > show_streamSelector ( false ) ;
2024-03-13 19:45:53 +01:00
int latency = dabSettings_p - > value ( " latency " , 5 ) . toInt ( ) ;
2024-04-03 18:44:52 +02:00
soundOut_p = nullptr ;
2024-10-09 17:57:23 +02:00
//
// If we do not have a TCP streamer, we go for one of the
// Portaudio and the Qt_audio alternatives.
// Default - and if Qt_Audio fails, we go for Portaudio
# ifndef TCP_STREAMER
2024-03-13 19:45:53 +01:00
QStringList streams ;
QString temp ;
2024-04-15 14:03:12 +02:00
QString s = dabSettings_p - > value ( S_SOUND_HANDLER , S_PORT_AUDIO ) .
2024-03-13 19:45:53 +01:00
toString ( ) ;
2024-03-24 14:07:49 +01:00
//
2024-10-09 17:57:23 +02:00
if ( s ! = S_PORT_AUDIO ) { // try Qt_Audio
2024-03-24 14:07:49 +01:00
try {
soundOut_p = new Qt_Audio ( dabSettings_p ) ;
streams = ( ( Qt_Audio * ) soundOut_p ) - > streams ( ) ;
temp =
dabSettings_p - > value ( QT_AUDIO_STREAM_NAME ,
" default " ) . toString ( ) ;
volumeSlider - > show ( ) ;
int volume =
dabSettings_p - > value ( QT_AUDIO_VOLUME , 50 ) . toInt ( ) ;
volumeSlider - > setValue ( volume ) ;
( ( Qt_Audio * ) soundOut_p ) - > setVolume ( volume ) ;
2024-04-10 19:49:55 +02:00
connect ( volumeSlider , & QSlider : : valueChanged ,
this , & RadioInterface : : setVolume ) ;
2024-03-24 14:07:49 +01:00
} catch ( . . . ) {
2024-10-14 13:12:03 +02:00
// fprintf (stderr, "QT_AUDIO does not find streams\n");
2024-03-24 14:07:49 +01:00
soundOut_p = nullptr ;
}
}
2024-10-09 17:57:23 +02:00
//
// we end up here if selection was PORT_AUDIO or using Qt_Audio failed
// as it does on U20
2024-03-24 14:07:49 +01:00
if ( soundOut_p = = nullptr ) {
2024-03-13 19:45:53 +01:00
soundOut_p = new audioSink ( latency ) ;
streams = ( ( audioSink * ) soundOut_p ) - > streams ( ) ;
temp =
dabSettings_p - > value ( AUDIO_STREAM_NAME ,
2024-02-25 14:18:27 +01:00
" default " ) . toString ( ) ;
2024-03-13 19:45:53 +01:00
}
if ( streams . size ( ) > 0 ) {
2024-10-14 13:12:03 +02:00
// for (auto s: streams)
// fprintf (stderr, "%s\n", s. toLatin1 (). data ());
2024-03-13 19:45:53 +01:00
configHandler_p - > fill_streamTable ( streams ) ;
configHandler_p - > show_streamSelector ( true ) ;
k = configHandler_p - > init_streamTable ( temp ) ;
2024-03-24 14:07:49 +01:00
if ( k > = 0 )
2024-03-13 19:45:53 +01:00
soundOut_p - > selectDevice ( k ) ;
2024-03-24 14:07:49 +01:00
configHandler_p - > connect_streamTable ( ) ;
2024-01-27 20:16:14 +01:00
}
2024-03-25 14:35:22 +01:00
else {
2024-03-27 16:24:49 +01:00
delete soundOut_p ;
soundOut_p = new audioPlayer ( ) ;
2024-03-25 14:35:22 +01:00
}
2024-10-09 17:57:23 +02:00
# else
soundOut_p = new tcpStreamer ( 20040 ) ;
techWindow_p - > hide ( ) ;
2024-01-27 20:16:14 +01:00
# endif
2024-10-09 17:57:23 +02:00
//
// some MOT, tetx and other data is stored in the Qt-DAB-files directory
// in home or tmp dir
2024-10-14 13:12:03 +02:00
QString tempPath = theFilenameFinder . basicPath ( ) ;
2024-10-09 17:57:23 +02:00
2024-09-23 10:19:31 +02:00
path_for_tiiFile = dabSettings_p - > value ( S_TII_PATH ,
2024-10-09 17:57:23 +02:00
tempPath ) . toString ( ) ;
2024-09-23 10:19:31 +02:00
path_for_tiiFile = checkDir ( path_for_tiiFile ) ;
2024-04-15 14:03:12 +02:00
path_for_pictures = dabSettings_p - > value ( S_PICTURES_PATH ,
2024-10-09 17:57:23 +02:00
tempPath ) . toString ( ) ;
path_for_pictures = checkDir ( path_for_pictures )
;
2024-04-15 14:03:12 +02:00
path_for_files = dabSettings_p - > value ( S_FILE_PATH ,
2024-10-09 17:57:23 +02:00
tempPath ) . toString ( ) ;
epgPath = dabSettings_p - > value ( S_EPG_PATH ,
tempPath ) . toString ( ) ;
epgPath = checkDir ( epgPath ) ;
2024-10-14 15:35:13 +02:00
2024-04-10 19:49:55 +02:00
connect ( & epgProcessor , & epgDecoder : : set_epgData ,
this , & RadioInterface : : set_epgData ) ;
2024-01-27 20:16:14 +01:00
// timer for autostart epg service
epgTimer . setSingleShot ( true ) ;
2024-04-14 12:47:14 +02:00
connect ( & epgTimer , & QTimer : : timeout ,
this , & RadioInterface : : epgTimer_timeOut ) ;
2024-03-13 19:45:53 +01:00
pauzeTimer . setSingleShot ( true ) ;
2024-04-14 12:47:14 +02:00
connect ( & pauzeTimer , & QTimer : : timeout ,
this , & RadioInterface : : show_pauzeSlide ) ;
2024-01-27 20:16:14 +01:00
my_timeTable = new timeTableHandler ( this ) ;
my_timeTable - > hide ( ) ;
2024-06-01 11:12:04 +02:00
connect ( & theScanlistHandler , & scanListHandler : : handle_scanListSelect ,
2024-04-14 12:47:14 +02:00
this , & RadioInterface : : handle_scanListSelect ) ;
2024-01-27 20:16:14 +01:00
// extract the channelnames and fill the combobox
2024-06-01 11:12:04 +02:00
QStringList res = theSCANHandler . getChannelNames ( ) ;
2024-01-27 20:16:14 +01:00
for ( auto & s : res )
channelSelector - > addItem ( s ) ;
2024-06-01 11:12:04 +02:00
QPalette p = theNewDisplay . ficError_display - > palette ( ) ;
2024-01-27 20:16:14 +01:00
p . setColor ( QPalette : : Highlight , Qt : : red ) ;
2024-06-01 11:12:04 +02:00
theNewDisplay . ficError_display - > setPalette ( p ) ;
2024-01-27 20:16:14 +01:00
p . setColor ( QPalette : : Highlight , Qt : : green ) ;
//
2024-07-28 12:47:27 +02:00
audioDumping = false ;
2024-07-27 15:30:56 +02:00
sourceDumping = false ;
2024-01-27 20:16:14 +01:00
ficBlocks = 0 ;
ficSuccess = 0 ;
total_ficError = 0 ;
total_fics = 0 ;
previous_idle_time = 0 ;
previous_total_time = 0 ;
// Connect the buttons for the color_settings
2024-04-14 12:47:14 +02:00
connect ( scanButton , & smallPushButton : : rightClicked ,
this , & RadioInterface : : color_scanButton ) ;
connect ( scanListButton , & newPushButton : : rightClicked ,
this , & RadioInterface : : color_scanListButton ) ;
connect ( presetButton , & newPushButton : : rightClicked ,
this , & RadioInterface : : color_presetButton ) ;
connect ( configButton , & smallPushButton : : rightClicked ,
this , & RadioInterface : : color_configButton ) ;
connect ( httpButton , & smallPushButton : : rightClicked ,
this , & RadioInterface : : color_httpButton ) ;
connect ( prevServiceButton , & smallPushButton : : rightClicked ,
this , & RadioInterface : : color_prevServiceButton ) ;
connect ( nextServiceButton , & smallPushButton : : rightClicked ,
this , & RadioInterface : : color_nextServiceButton ) ;
connect ( spectrumButton , & smallPushButton : : rightClicked ,
this , & RadioInterface : : color_spectrumButton ) ;
2024-01-27 20:16:14 +01:00
//
//
2024-04-14 12:47:14 +02:00
connect ( techWindow_p , & techData : : handle_timeTable ,
this , & RadioInterface : : handle_timeTable ) ;
2024-06-01 11:12:04 +02:00
connect ( & theNewDisplay , & displayWidget : : mouseClick ,
2024-04-14 12:47:14 +02:00
this , & RadioInterface : : handle_iqSelector ) ;
2024-01-27 20:16:14 +01:00
// display the version
version = " Qt-DAB-6. " + SystemVersion ;
2024-04-14 12:47:14 +02:00
connect ( aboutLabel , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_aboutLabel ) ;
2024-01-27 20:16:14 +01:00
2024-04-14 12:47:14 +02:00
connect ( soundLabel , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_muteButton ) ;
connect ( snrLabel , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_snrLabel ) ;
2024-01-27 20:16:14 +01:00
2024-06-01 11:12:04 +02:00
// if (theTIIProcessor. has_tiiFile ())
2024-02-25 14:18:27 +01:00
configHandler_p - > enable_loadLib ( ) ;
2024-04-14 18:35:47 +02:00
// else
// httpButton -> setEnabled (false);
2024-01-27 20:16:14 +01:00
channel . etiActive = false ;
show_pauzeSlide ( ) ;
// and start the timer(s)
// The displaytimer is there to show the number of
// seconds running and handle - if available - the tii data
displayTimer . setInterval ( 1000 ) ;
2024-04-14 12:47:14 +02:00
connect ( & displayTimer , & QTimer : : timeout ,
this , & RadioInterface : : updateTimeDisplay ) ;
2024-01-27 20:16:14 +01:00
displayTimer . start ( 1000 ) ;
numberofSeconds = 0 ;
// timer for scanning
channelTimer . setSingleShot ( true ) ;
channelTimer . setInterval ( 10000 ) ;
2024-04-14 12:47:14 +02:00
connect ( & channelTimer , & QTimer : : timeout ,
this , & RadioInterface : : channel_timeOut ) ;
2024-01-27 20:16:14 +01:00
//
// presetTimer
presetTimer . setSingleShot ( true ) ;
2024-04-14 12:47:14 +02:00
connect ( & presetTimer , & QTimer : : timeout ,
this , & RadioInterface : : setPresetService ) ;
2024-01-27 20:16:14 +01:00
//
// timer for muting
muteTimer . setSingleShot ( true ) ;
set_Colors ( ) ;
//
2024-04-14 18:35:47 +02:00
// do we have a known device from previous invocations?
2024-01-27 20:16:14 +01:00
inputDevice_p = nullptr ;
h =
2024-02-25 14:18:27 +01:00
dabSettings_p - > value ( SELECTED_DEVICE ,
" no device " ) . toString ( ) ;
2024-02-16 15:46:54 +01:00
bool b = configHandler_p - > findDevice ( h ) ;
if ( b ) {
inputDevice_p = create_device ( h ) ;
2024-01-27 20:16:14 +01:00
}
//
// do we show controls?
2024-02-25 14:18:27 +01:00
bool visible =
dabSettings_p - > value ( CONFIG_WIDGET_VISIBLE ,
0 ) . toInt ( ) ! = 0 ;
if ( visible ) {
2024-02-16 15:46:54 +01:00
configHandler_p - > show ( ) ;
2024-01-27 20:16:14 +01:00
}
2024-04-14 12:47:14 +02:00
connect ( configButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_configButton ) ;
2024-01-27 20:16:14 +01:00
2024-02-25 14:18:27 +01:00
if ( dabSettings_p - > value ( SNR_WIDGET_VISIBLE , 0 ) . toInt ( ) ! = 0 )
2024-06-01 11:12:04 +02:00
theSNRViewer . show ( ) ;
2024-01-27 20:16:14 +01:00
else
2024-06-01 11:12:04 +02:00
theSNRViewer . hide ( ) ;
2024-02-25 14:18:27 +01:00
if ( dabSettings_p - > value ( TECHDATA_VISIBLE , 0 ) . toInt ( ) = = 1 )
2024-01-27 20:16:14 +01:00
techWindow_p - > show ( ) ;
2024-01-29 15:47:49 +01:00
dynamicLabel - > setTextInteractionFlags ( Qt : : TextSelectableByMouse ) ;
dynamicLabel - > setToolTip ( " The text (or parts of it) of the dynamic label can be copied. Selecting the text with the mouse and clicking the right hand mouse button shows a small menu with which the text can be put into the clipboard " ) ;
2024-02-25 14:18:27 +01:00
//
// Until the opposite is known to be true:
nextService . channel = " " ;
nextService . serviceName = " " ;
nextService . valid = false ;
2024-01-27 20:16:14 +01:00
// if a device was selected, we just start, otherwise
// we wait until one is selected
2024-02-25 14:18:27 +01:00
connectGUI ( ) ;
2024-01-27 20:16:14 +01:00
if ( inputDevice_p ! = nullptr ) {
2024-04-14 12:47:14 +02:00
doStart_direct ( ) ;
2024-02-25 14:18:27 +01:00
qApp - > installEventFilter ( this ) ;
return ;
2024-01-27 20:16:14 +01:00
}
2024-02-25 14:18:27 +01:00
if ( ! visible ) { // make it visible
dabSettings_p - > setValue ( CONFIG_WIDGET_VISIBLE , 1 ) ;
dabSettings_p - > setValue ( DEVICE_WIDGET_VISIBLE , 1 ) ;
2024-01-27 20:16:14 +01:00
}
2024-02-16 15:46:54 +01:00
configHandler_p - > show ( ) ;
configHandler_p - > connectDevices ( ) ;
2024-01-27 20:16:14 +01:00
qApp - > installEventFilter ( this ) ;
2024-02-25 14:18:27 +01:00
//
// and just wait to see what device is selected
2024-01-27 20:16:14 +01:00
}
//
// doStart (QString) is called when - on startup - NO device
// was registered to be used, and the user presses the
// selectDevice comboBox
void RadioInterface : : doStart ( const QString & dev ) {
inputDevice_p = create_device ( dev ) ;
// Some buttons should not be touched before we have a device
if ( inputDevice_p = = nullptr ) {
return ;
}
2024-04-14 12:47:14 +02:00
doStart_direct ( ) ;
2024-01-27 20:16:14 +01:00
}
//
2024-02-25 14:18:27 +01:00
// we (re)start a device, if it happens to be a regular
// device, check for a preset name
2024-04-14 12:47:14 +02:00
void RadioInterface : : doStart_direct ( ) {
2024-04-15 14:03:12 +02:00
disconnect ( channelSelector ,
2024-10-07 19:35:30 +02:00
# if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
qOverload < const QString & > ( & QComboBox : : textActivated ) ,
# else
2024-04-15 14:03:12 +02:00
qOverload < const QString & > ( & QComboBox : : activated ) ,
2024-10-07 19:35:30 +02:00
# endif
2024-04-14 12:47:14 +02:00
this , & RadioInterface : : handle_channelSelector ) ;
2024-02-25 14:18:27 +01:00
nextService = checkPresets ( ) ;
if ( nextService . valid ) {
2024-02-16 15:46:54 +01:00
int k = channelSelector - > findText ( nextService . channel ) ;
2024-01-27 20:16:14 +01:00
if ( k ! = - 1 )
channelSelector - > setCurrentIndex ( k ) ;
}
else
channelSelector - > setCurrentIndex ( 0 ) ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_RADIO_STARTS , inputDevice_p - > deviceName ( ) ,
channelSelector - > currentText ( ) ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler = new ofdmHandler ( this ,
2024-01-27 20:16:14 +01:00
inputDevice_p , & globals , dabSettings_p ) ;
channel . cleanChannel ( ) ;
the_ensembleHandler - > reset ( ) ;
the_ensembleHandler - > setMode ( ! inputDevice_p - > isFileInput ( ) ) ;
2024-02-25 14:18:27 +01:00
if ( dabSettings_p - > value ( DEVICE_WIDGET_VISIBLE , 0 ) . toInt ( ) ! = 0 )
2024-01-27 20:16:14 +01:00
inputDevice_p - > setVisibility ( true ) ;
2024-04-03 18:44:52 +02:00
2024-01-27 20:16:14 +01:00
// Just to be sure we disconnect here.
// It would have been helpful to have a function
// testing whether or not a connection exists, we need a kind
// of "reset"
2024-02-16 15:46:54 +01:00
configHandler_p - > disconnectDevices ( ) ;
configHandler_p - > reconnectDevices ( ) ;
2024-04-15 14:03:12 +02:00
connect ( channelSelector ,
2024-10-07 19:35:30 +02:00
# if QT_VERSION >= QT_VERSION_CHECK(5, 15, 2)
qOverload < const QString & > ( & QComboBox : : textActivated ) ,
# else
2024-04-15 14:03:12 +02:00
qOverload < const QString & > ( & QComboBox : : activated ) ,
2024-10-07 19:35:30 +02:00
# endif
2024-04-14 12:47:14 +02:00
this , & RadioInterface : : handle_channelSelector ) ;
2024-02-25 14:18:27 +01:00
if ( configHandler_p - > tii_detector_active ( ) )
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_tiiDetectorMode ( true ) ;
2024-02-25 14:18:27 +01:00
2024-02-16 15:46:54 +01:00
if ( nextService . valid ) {
int switchDelay = configHandler_p - > switchDelayValue ( ) ;
2024-01-27 20:16:14 +01:00
presetTimer . setSingleShot ( true ) ;
2024-02-16 15:46:54 +01:00
presetTimer . setInterval ( switchDelay ) ;
presetTimer . start ( switchDelay ) ;
2024-01-27 20:16:14 +01:00
// after the preset timer signals, the service will be started
2024-02-25 14:18:27 +01:00
}
2024-07-27 15:30:56 +02:00
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
2024-04-19 18:34:50 +02:00
int auto_http = dabSettings_p - > value ( " auto_http " , 0 ) . toInt ( ) ;
if ( ( auto_http ! = 0 ) & & ( localPos . latitude ! = 0 ) ) {
bool succ = autoStart_http ( ) ;
if ( succ )
httpButton - > setText ( " http-on " ) ;
}
2024-01-27 20:16:14 +01:00
running . store ( true ) ;
}
RadioInterface : : ~ RadioInterface ( ) {
fprintf ( stderr , " radioInterface is deleted \n " ) ;
}
2024-02-25 14:18:27 +01:00
dabService RadioInterface : : checkPresets ( ) {
dabService res ;
res . channel = " " ;
res . serviceName = " " ;
res . valid = false ;
if ( inputDevice_p - > isFileInput ( ) )
return res ;
QString preset = dabSettings_p - > value ( PRESET_NAME , " " ) . toString ( ) ;
if ( preset = = " " )
return res ;
2024-03-13 19:45:53 +01:00
QStringList list = splitter ( preset ) ;
2024-02-25 14:18:27 +01:00
if ( list . size ( ) ! = 2 )
return res ;
res . channel = list . at ( 0 ) ;
res . serviceName = list . at ( 1 ) ;
res . valid = true ;
return res ;
}
2024-01-27 20:16:14 +01:00
//
2024-03-04 14:45:33 +01:00
// no_signal_found is called when scanning is on by the
// ofdm handler
void RadioInterface : : no_signal_found ( ) {
channel_timeOut ( ) ;
2024-01-27 20:16:14 +01:00
}
///////////////////////////////////////////////////////////////////////////
//
// a slot, called by the fic/fib handlers
void RadioInterface : : add_to_ensemble ( const QString & serviceName ,
2024-03-27 16:24:49 +01:00
int32_t SId , int subChId ) {
2024-01-27 20:16:14 +01:00
if ( ! running . load ( ) )
return ;
serviceId ed ;
ed . name = serviceName ;
ed . SId = SId ;
ed . subChId = subChId ;
ed . channel = channel . channelName ;
bool added = the_ensembleHandler - > add_to_ensemble ( ed ) ;
if ( added ) {
channel . nrServices + + ;
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . active ( ) )
theSCANHandler . addService ( channel . channelName ) ;
if ( theSCANHandler . active ( ) & & ! theSCANHandler . scan_to_data ( ) ) {
theScanlistHandler . addElement ( channel . channelName ,
2024-01-27 20:16:14 +01:00
serviceName ) ;
}
}
2024-02-25 14:18:27 +01:00
2024-01-27 20:16:14 +01:00
if ( ( channel . serviceCount = = channel . nrServices ) & &
2024-06-01 11:12:04 +02:00
! theSCANHandler . active ( ) ) {
2024-03-04 14:45:33 +01:00
// presetTimer. stop ();
2024-01-27 20:16:14 +01:00
setPresetService ( ) ;
}
}
//
// The ensembleId is written as hexadecimal, however, the
// number display of Qt is only 7 segments ...
static
QString hextoString ( int v ) {
QString res ;
for ( int i = 0 ; i < 4 ; i + + ) {
uint8_t t = ( v & 0xF000 ) > > 12 ;
QChar c = t < = 9 ? ( char ) ( ' 0 ' + t ) : ( char ) ( ' A ' + t - 10 ) ;
res . append ( c ) ;
v < < = 4 ;
}
return res ;
}
// a slot, called by the fib processor
void RadioInterface : : name_of_ensemble ( int id , const QString & v ) {
QString s ;
if ( ! running . load ( ) )
return ;
ensembleId - > setText ( v + QString ( " ( " ) + hextoString ( id ) + QString ( " ) " ) ) ;
2024-09-04 09:46:23 +02:00
transmitter_country - > setText ( channel . countryName ) ;
2024-01-27 20:16:14 +01:00
channel . ensembleName = v ;
channel . Eid = id ;
//
// id we are scanning "to data", we reached the end
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . scan_to_data ( ) )
2024-01-27 20:16:14 +01:00
stopScanning ( ) ;
else
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . active ( ) & & theSCANHandler . scan_single ( ) )
theSCANHandler . addEnsemble ( channelSelector - > currentText ( ) , v ) ;
2024-01-27 20:16:14 +01:00
// ... and is we are not scanning, clicking the ensembleName
// has effect
2024-06-01 11:12:04 +02:00
if ( ! theSCANHandler . active ( ) )
2024-04-14 12:47:14 +02:00
connect ( ensembleId , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_contentButton ) ;
2024-01-27 20:16:14 +01:00
}
//
///////////////////////////////////////////////////////////////////////////
void RadioInterface : : handle_contentButton ( ) {
2024-06-01 11:12:04 +02:00
QStringList s = theOFDMHandler - > basicPrint ( ) ;
2024-01-27 20:16:14 +01:00
if ( contentTable_p ! = nullptr ) {
contentTable_p - > hide ( ) ;
delete contentTable_p ;
contentTable_p = nullptr ;
return ;
}
2024-04-07 14:58:26 +02:00
QString headLine = build_headLine ( ) ;
2024-01-27 20:16:14 +01:00
contentTable_p = new contentTable ( this , dabSettings_p ,
channel . channelName ,
2024-06-01 11:12:04 +02:00
theOFDMHandler - > scanWidth ( ) ) ;
2024-04-14 12:47:14 +02:00
connect ( contentTable_p , & contentTable : : goService ,
this , & RadioInterface : : handle_contentSelector ) ;
2024-01-27 20:16:14 +01:00
2024-04-07 14:58:26 +02:00
contentTable_p - > addLine ( headLine ) ;
2024-01-27 20:16:14 +01:00
// contentTable_p -> addLine ("\n");
2024-02-25 14:18:27 +01:00
for ( auto & ss : s )
contentTable_p - > addLine ( ss ) ;
2024-01-27 20:16:14 +01:00
contentTable_p - > show ( ) ;
2024-03-04 14:45:33 +01:00
if ( configHandler_p - > upload_selector_active ( ) ) {
2024-03-13 19:45:53 +01:00
try {
uploader the_uploader ;
QMessageBox : : StandardButton reply =
2024-03-04 14:45:33 +01:00
QMessageBox : : question ( this ,
2024-03-13 19:45:53 +01:00
" upload content to fmlist.org? " , " " ,
2024-03-04 14:45:33 +01:00
QMessageBox : : Yes | QMessageBox : : No ) ;
2024-03-13 19:45:53 +01:00
if ( reply = = QMessageBox : : Yes )
the_uploader . loadUp ( channel . ensembleName ,
channel . Eid ,
channel . channelName ,
contentTable_p - > upload ( ) ) ;
} catch ( . . . ) { }
2024-03-04 14:45:33 +01:00
}
2024-01-27 20:16:14 +01:00
}
2024-07-16 19:52:55 +02:00
QString RadioInterface : : checkDir ( const QString & s ) {
2024-01-27 20:16:14 +01:00
QString dir = s ;
if ( ! dir . endsWith ( QChar ( ' / ' ) ) )
dir + = QChar ( ' / ' ) ;
if ( QDir ( dir ) . exists ( ) )
return dir ;
QDir ( ) . mkpath ( dir ) ;
return dir ;
}
void RadioInterface : : handle_motObject ( QByteArray result ,
QString objectName ,
int contentType ,
bool dirElement ,
bool backgroundFlag ) {
QString realName ;
switch ( getContentBaseType ( ( MOTContentType ) contentType ) ) {
case MOTBaseTypeGeneralData :
break ;
case MOTBaseTypeText :
save_MOTtext ( result , contentType , objectName ) ;
break ;
case MOTBaseTypeImage :
show_MOTlabel ( result , contentType ,
objectName , dirElement , backgroundFlag ) ;
break ;
case MOTBaseTypeAudio :
break ;
case MOTBaseTypeVideo :
break ;
case MOTBaseTypeTransport :
save_MOTObject ( result , objectName ) ;
break ;
case MOTBaseTypeSystem :
break ;
case MOTBaseTypeApplication : // epg data
if ( epgPath = = " " )
return ;
if ( objectName = = QString ( " " ) )
objectName = " epg file " ;
objectName = epgPath + objectName ;
2024-04-22 20:35:15 +02:00
{ QString temp = objectName ;
2024-01-27 20:16:14 +01:00
temp = temp . left ( temp . lastIndexOf ( QChar ( ' / ' ) ) ) ;
if ( ! QDir ( temp ) . exists ( ) )
QDir ( ) . mkpath ( temp ) ;
std : : vector < uint8_t > epgData ( result . begin ( ) ,
result . end ( ) ) ;
// uint32_t ensembleId =
2024-06-01 11:12:04 +02:00
// theOFDMHandler -> get_ensembleId ();
2024-01-27 20:16:14 +01:00
uint32_t currentSId =
the_ensembleHandler - > extract_SId ( objectName ) ;
uint32_t julianDate =
2024-06-01 11:12:04 +02:00
theOFDMHandler - > julianDate ( ) ;
2024-01-27 20:16:14 +01:00
int subType =
getContentSubType ( ( MOTContentType ) contentType ) ;
epgProcessor . process_epg ( epgData . data ( ) ,
epgData . size ( ) , currentSId ,
subType ,
julianDate ) ;
2024-02-16 15:46:54 +01:00
if ( configHandler_p - > epg2_active ( ) ) {
2024-01-27 20:16:14 +01:00
epgHandler . decode ( epgData ,
QDir : : toNativeSeparators ( objectName ) ) ;
}
}
return ;
case MOTBaseTypeProprietary :
break ;
}
}
void RadioInterface : : save_MOTtext ( QByteArray & result ,
int contentType ,
const QString & name ) {
( void ) contentType ;
if ( path_for_files = = " " )
return ;
QString textName = QDir : : toNativeSeparators ( path_for_files + name ) ;
FILE * x = fopen ( textName . toUtf8 ( ) . data ( ) , " w+b " ) ;
if ( x = = nullptr )
fprintf ( stderr , " cannot write file %s \n " ,
textName . toUtf8 ( ) . data ( ) ) ;
else {
fprintf ( stderr , " going to write file %s \n " ,
textName . toUtf8 ( ) . data ( ) ) ;
( void ) fwrite ( result . data ( ) , 1 , result . length ( ) , x ) ;
fclose ( x ) ;
}
}
void RadioInterface : : save_MOTObject ( QByteArray & result ,
QString name ) {
if ( path_for_files = = " " )
return ;
if ( name = = " " ) {
static int counter = 0 ;
name = " motObject_ " + QString : : number ( counter ) ;
counter + + ;
}
save_MOTtext ( result , 5 , name ) ;
}
// MOT slide, to show
void RadioInterface : : show_MOTlabel ( QByteArray & data ,
int contentType ,
const QString & pictureName ,
int dirs ,
bool backgroundFlag ) {
const char * type ;
if ( ! running . load ( ) | | ( pictureName = = QString ( " " ) ) )
return ;
( void ) dirs ;
switch ( static_cast < MOTContentType > ( contentType ) ) {
case MOTCTImageGIF :
type = " GIF " ;
break ;
case MOTCTImageJFIF :
type = " JPG " ;
break ;
case MOTCTImageBMP :
type = " BMP " ;
break ;
case MOTCTImagePNG :
type = " PNG " ;
break ;
default :
return ;
}
2024-02-25 14:18:27 +01:00
if ( ( int_configValue ( " saveSlides " , 0 ) ! = 0 ) & &
2024-02-16 15:46:54 +01:00
( path_for_pictures ! = " " ) ) {
2024-01-27 20:16:14 +01:00
QString pict = path_for_pictures + pictureName ;
QString temp = pict ;
temp = temp . left ( temp . lastIndexOf ( QChar ( ' / ' ) ) ) ;
if ( ! QDir ( temp ) . exists ( ) )
QDir ( ) . mkpath ( temp ) ;
pict = QDir : : toNativeSeparators ( pict ) ;
FILE * x = fopen ( pict . toUtf8 ( ) . data ( ) , " w+b " ) ;
if ( x = = nullptr )
fprintf ( stderr , " cannot write file %s \n " ,
pict . toUtf8 ( ) . data ( ) ) ;
else {
fprintf ( stderr , " going to write file %s \n " ,
pict . toUtf8 ( ) . data ( ) ) ;
( void ) fwrite ( data . data ( ) , 1 , data . length ( ) , x ) ;
fclose ( x ) ;
}
}
if ( backgroundFlag )
return ;
if ( channel . currentService . valid & &
channel . currentService . announcement_going )
return ;
QPixmap p ;
if ( p . loadFromData ( data , type ) )
displaySlide ( p ) ;
}
//
// sendDatagram is triggered by the ip handler,
void RadioInterface : : sendDatagram ( int length ) {
2024-04-22 20:35:15 +02:00
uint8_t * localBuffer = dynVec ( uint8_t , length ) ;
2024-01-27 20:16:14 +01:00
2024-06-01 11:12:04 +02:00
if ( theDataBuffer . GetRingBufferReadAvailable ( ) < length ) {
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " Something went wrong \n " ) ;
return ;
}
2024-06-01 11:12:04 +02:00
theDataBuffer . getDataFromBuffer ( localBuffer , length ) ;
2024-01-27 20:16:14 +01:00
# ifdef _SEND_DATAGRAM_
if ( running . load ( ) ) {
dataOut_socket . writeDatagram ( ( const char * ) localBuffer , length ,
QHostAddress ( ipAddress ) ,
port ) ;
}
# endif
}
//
// tdcData is triggered by the backend.
void RadioInterface : : handle_tdcdata ( int frametype , int length ) {
# ifdef DATA_STREAMER
2024-04-22 20:35:15 +02:00
uint8_t * localBuffer = dynVec ( uint8_t , length + 8 ) ;
2024-01-27 20:16:14 +01:00
# endif
( void ) frametype ;
if ( ! running . load ( ) )
return ;
2024-06-01 11:12:04 +02:00
if ( theDataBuffer . GetRingBufferReadAvailable ( ) < length ) {
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " Something went wrong \n " ) ;
return ;
}
# ifdef DATA_STREAMER
2024-03-27 16:24:49 +01:00
// fprintf (stderr, "%d\n", length);
2024-06-01 11:12:04 +02:00
theDataBuffer . getDataFromBuffer ( & localBuffer [ 8 ] , length ) ;
2024-01-27 20:16:14 +01:00
localBuffer [ 0 ] = 0xFF ;
localBuffer [ 1 ] = 0x00 ;
localBuffer [ 2 ] = 0xFF ;
localBuffer [ 3 ] = 0x00 ;
localBuffer [ 4 ] = ( length & 0xFF ) > > 8 ;
localBuffer [ 5 ] = length & 0xFF ;
localBuffer [ 6 ] = 0x00 ;
localBuffer [ 7 ] = frametype = = 0 ? 0 : 0xFF ;
if ( running . load ( ) )
dataStreamer_p - > sendData ( localBuffer , length + 8 ) ;
# endif
}
/**
2024-10-09 17:57:23 +02:00
* If a " change in configuration " is detected , we have to
* restart the selected service - if any . s
* If the service is a secondary service , it might be the case
* that we have to start the main service
2024-01-27 20:16:14 +01:00
* how do we find that ?
*
* Response to a signal , so we presume that the signaling body exists
* signal may be pending though
*/
2024-09-14 14:57:15 +02:00
void RadioInterface : : changeinConfiguration ( const QStringList & notInOld ,
const QStringList & notInNew ) {
2024-06-01 11:12:04 +02:00
if ( ! running . load ( ) | | theOFDMHandler = = nullptr )
2024-01-27 20:16:14 +01:00
return ;
2024-09-14 14:57:15 +02:00
2024-01-27 20:16:14 +01:00
dabService s ;
if ( channel . currentService . valid ) {
s = channel . currentService ;
s . serviceName = channel . currentService . serviceName ;
s . SId = channel . currentService . SId ;
s . SCIds = channel . currentService . SCIds ;
s . channel = channel . channelName ;
s . valid = true ;
}
stopService ( channel . currentService ) ;
stopScanning ( ) ;
//
// we stop all secondary services as well, but we maintain theer
// description, file descriptors remain of course
//
if ( channel . etiActive )
2024-06-01 11:12:04 +02:00
theOFDMHandler - > reset_etiGenerator ( ) ;
2024-01-27 20:16:14 +01:00
for ( uint16_t i = 0 ; i < channel . backgroundServices . size ( ) ; i + + )
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_service ( channel . backgroundServices . at ( i ) . subChId ,
2024-01-27 20:16:14 +01:00
BACK_GROUND ) ;
// we rebuild the services list from the fib and
// then we (try to) restart the service
2024-02-16 15:46:54 +01:00
int serviceOrder = configHandler_p - > get_serviceOrder ( ) ;
2024-01-27 20:16:14 +01:00
std : : vector < serviceId > serviceList =
2024-06-01 11:12:04 +02:00
theOFDMHandler - > get_services ( serviceOrder ) ;
2024-01-27 20:16:14 +01:00
the_ensembleHandler - > reset ( ) ;
channel . nrServices = 0 ;
for ( auto & serv : serviceList ) {
serv . channel = channel . channelName ;
if ( the_ensembleHandler - > add_to_ensemble ( serv ) )
channel . nrServices + + ;
}
// Of course, the (sub)service may have disappeared
if ( s . valid ) {
2024-06-01 11:12:04 +02:00
QString ss = theOFDMHandler - > find_service ( s . SId , s . SCIds ) ;
2024-01-27 20:16:14 +01:00
if ( ss ! = " " ) {
startService ( s ) ;
return ;
}
//
2024-09-14 14:57:15 +02:00
show_changeLabel ( notInOld , notInNew ) ;
2024-01-27 20:16:14 +01:00
// The service is gone, it may be the subservice of another one
s . SCIds = 0 ;
s . serviceName =
2024-06-01 11:12:04 +02:00
theOFDMHandler - > find_service ( s . SId , 0 ) ;
2024-01-27 20:16:14 +01:00
if ( s . serviceName ! = " " ) {
startService ( s ) ;
}
}
//
// we also have to restart all background services,
for ( uint16_t i = 0 ; i < channel . backgroundServices . size ( ) ; i + + ) {
2024-06-01 11:12:04 +02:00
QString ss = theOFDMHandler - > find_service ( s . SId , s . SCIds ) ;
2024-01-27 20:16:14 +01:00
if ( ss = = " " ) { // it is gone, close the file if any
if ( channel . backgroundServices . at ( i ) . fd ! = nullptr )
fclose ( channel . backgroundServices . at ( i ) . fd ) ;
channel . backgroundServices . erase
( channel . backgroundServices . begin ( ) + i ) ;
}
else { // (re)start the service
2024-03-27 16:24:49 +01:00
audiodata ad ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > data_for_audioservice ( ss , ad ) ;
2024-03-27 16:24:49 +01:00
if ( ad . defined ) {
2024-01-27 20:16:14 +01:00
FILE * f = channel . backgroundServices . at ( i ) . fd ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - >
set_audioChannel ( ad , & theAudioBuffer , f , BACK_GROUND ) ;
2024-01-27 20:16:14 +01:00
channel . backgroundServices . at ( i ) . subChId = ad . subchId ;
}
else {
packetdata pd ;
2024-07-16 19:52:55 +02:00
theOFDMHandler - > data_for_packetservice ( ss , pd , 0 ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - >
set_dataChannel ( pd , & theDataBuffer , BACK_GROUND ) ;
2024-01-27 20:16:14 +01:00
channel . backgroundServices . at ( i ) . subChId = pd . subchId ;
}
}
}
}
//
// In order to not overload with an enormous amount of
// signals, we trigger this function at most 10 times a second
//
void RadioInterface : : newAudio ( int amount , int rate ,
bool ps , bool sbr ) {
if ( ! running . load ( ) )
return ;
static int teller = 0 ;
// if (!techWindow_p -> isHidden ()) {
teller + + ;
if ( teller > 10 ) {
teller = 0 ;
if ( ! techWindow_p - > isHidden ( ) )
techWindow_p - > show_rate ( rate , ps , sbr ) ;
2024-02-06 15:37:07 +01:00
audiorateLabel - > setStyleSheet ( labelStyle ) ;
2024-01-27 20:16:14 +01:00
audiorateLabel - > setText ( QString : : number ( rate ) ) ;
if ( ! ps )
psLabel - > setText ( " " ) ;
else {
2024-02-06 15:37:07 +01:00
psLabel - > setStyleSheet ( labelStyle ) ;
2024-01-27 20:16:14 +01:00
psLabel - > setText ( " ps " ) ;
}
if ( ! sbr )
sbrLabel - > setText ( " " ) ;
else {
2024-02-06 15:37:07 +01:00
sbrLabel - > setStyleSheet ( labelStyle ) ;
2024-01-27 20:16:14 +01:00
sbrLabel - > setText ( " sbr " ) ;
}
}
std : : complex < int16_t > vec [ amount ] ;
2024-06-01 11:12:04 +02:00
while ( theAudioBuffer . GetRingBufferReadAvailable ( ) > amount ) {
theAudioBuffer . getDataFromBuffer ( vec , amount ) ;
2024-01-27 20:16:14 +01:00
# ifdef HAVE_PLUTO_RXTX
if ( streamerOut_p ! = nullptr )
streamerOut_p - > audioOut ( vec , amount , rate ) ;
# endif
//
std : : vector < float > tmpBuffer ;
2024-06-01 11:12:04 +02:00
int size = theAudioConverter . convert ( vec , amount , rate , tmpBuffer ) ;
2024-01-27 20:16:14 +01:00
if ( ! muteTimer . isActive ( ) )
soundOut_p - > audioOutput ( tmpBuffer . data ( ) , size ) ;
if ( ! techWindow_p - > isHidden ( ) ) {
theTechData . putDataIntoBuffer ( vec , amount ) ;
techWindow_p - > audioDataAvailable ( amount , rate ) ;
}
}
}
//
/////////////////////////////////////////////////////////////////////////////
//
/**
* \ brief TerminateProcess
* Pretty critical , since there are many threads involved
* A clean termination is what is needed , regardless of the GUI
*/
void RadioInterface : : TerminateProcess ( ) {
running . store ( false ) ;
2024-06-01 11:12:04 +02:00
theSCANHandler . hide ( ) ;
2024-01-27 20:16:14 +01:00
stopScanning ( ) ;
2024-06-01 11:12:04 +02:00
while ( theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
usleep ( 1000 ) ;
hideButtons ( ) ;
2024-06-01 11:12:04 +02:00
theDXDisplay . hide ( ) ;
2024-04-15 14:03:12 +02:00
store_widget_position ( dabSettings_p , this , S_MAIN_WIDGET ) ;
2024-06-01 11:12:04 +02:00
theNewDisplay . hide ( ) ;
2024-01-27 20:16:14 +01:00
//
# ifdef DATA_STREAMER
fprintf ( stderr , " going to close the dataStreamer \n " ) ;
delete dataStreamer_p ;
# endif
# ifdef CLOCK_STREAMER
fprintf ( stderr , " going to close the clockstreamer \n " ) ;
delete clockStreamer_p ;
# endif
displayTimer . stop ( ) ;
channelTimer . stop ( ) ;
presetTimer . stop ( ) ;
epgTimer . stop ( ) ;
soundOut_p - > stop ( ) ;
if ( dlTextFile ! = nullptr )
fclose ( dlTextFile ) ;
# ifdef HAVE_PLUTO_RXTX
if ( streamerOut_p ! = nullptr )
streamerOut_p - > stop ( ) ;
# endif
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler ! = nullptr )
theOFDMHandler - > stop ( ) ;
2024-01-27 20:16:14 +01:00
the_ensembleHandler - > hide ( ) ;
2024-02-25 14:18:27 +01:00
// delete the_ensembleHandler;
2024-02-16 15:46:54 +01:00
configHandler_p - > hide ( ) ;
2024-03-30 19:39:33 +01:00
delete configHandler_p ;
2024-01-27 20:16:14 +01:00
techWindow_p - > hide ( ) ;
delete techWindow_p ;
if ( contentTable_p ! = nullptr ) {
contentTable_p - > clearTable ( ) ;
contentTable_p - > hide ( ) ;
delete contentTable_p ;
}
2024-04-10 19:49:55 +02:00
if ( mapHandler ! = nullptr )
mapHandler - > stop ( ) ;
2024-01-27 20:16:14 +01:00
// just save a few checkbox settings that are not
if ( scanTable_p ! = nullptr ) {
scanTable_p - > clearTable ( ) ;
scanTable_p - > hide ( ) ;
delete scanTable_p ;
}
2024-06-01 11:12:04 +02:00
theSCANHandler . hide ( ) ;
2024-01-27 20:16:14 +01:00
stopFramedumping ( ) ;
stop_sourcedumping ( ) ;
stopAudiodumping ( ) ;
theScheduler . hide ( ) ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_RADIO_STOPS ) ;
2024-01-27 20:16:14 +01:00
usleep ( 1000 ) ; // pending signals
// everything should be halted by now
dabSettings_p - > sync ( ) ;
2024-06-01 11:12:04 +02:00
theSNRViewer . hide ( ) ;
if ( theOFDMHandler ! = nullptr )
delete theOFDMHandler ;
2024-01-27 20:16:14 +01:00
if ( inputDevice_p ! = nullptr )
delete inputDevice_p ;
delete soundOut_p ;
2024-06-01 11:12:04 +02:00
theScanlistHandler . hide ( ) ;
2024-01-27 20:16:14 +01:00
delete my_timeTable ;
// close();
fprintf ( stderr , " .. end the radio silences \n " ) ;
}
//
void RadioInterface : : updateTimeDisplay ( ) {
if ( ! running . load ( ) )
return ;
numberofSeconds + + ;
int16_t numberHours = numberofSeconds / 3600 ;
int16_t numberMinutes = ( numberofSeconds / 60 ) % 60 ;
QString text = QString ( " runtime " ) +
QString : : number ( numberHours ) + " hr, "
+ QString : : number ( numberMinutes ) + " min " ;
runtimeDisplay - > setText ( text ) ;
if ( ( numberofSeconds % 2 ) = = 0 ) {
2024-08-15 13:16:44 +02:00
size_t idle_time = 0 , total_time ;
2024-01-27 20:16:14 +01:00
get_cpu_times ( idle_time , total_time ) ;
const float idle_time_delta =
static_cast < float > ( idle_time - previous_idle_time ) ;
const float total_time_delta =
static_cast < float > ( total_time - previous_total_time ) ;
const float utilization = 100.0 * ( 1.0 - idle_time_delta / total_time_delta ) ;
2024-02-16 15:46:54 +01:00
configHandler_p - > showLoad ( utilization ) ;
2024-01-27 20:16:14 +01:00
// cpuMonitor -> display (QString("%1").arg(utilization, 0, 'f', 2));
previous_idle_time = idle_time ;
previous_total_time = total_time ;
}
//
// The timer runs autonomously, so it might happen
// that it rings when there is no processor running
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler = = nullptr )
2024-01-27 20:16:14 +01:00
return ;
2024-03-24 14:07:49 +01:00
if ( ! techWindow_p - > isHidden ( ) ) {
2024-01-27 20:16:14 +01:00
if ( soundOut_p - > hasMissed ( ) ) {
int xxx = ( ( audioSink * ) soundOut_p ) - > missed ( ) ;
techWindow_p - > showMissed ( xxx ) ;
}
}
}
//
// precondition: everything is quiet
deviceHandler * RadioInterface : : create_device ( const QString & s ) {
2024-06-01 11:12:04 +02:00
deviceHandler * inputDevice = theDeviceChoser . createDevice ( s , version ) ;
2024-01-27 20:16:14 +01:00
if ( inputDevice = = nullptr )
return nullptr ;
channel . realChannel = ! inputDevice - > isFileInput ( ) ;
if ( channel . realChannel )
showButtons ( ) ;
else
hideButtons ( ) ;
the_ensembleHandler - > setMode ( channel . realChannel ) ;
2024-04-14 12:47:14 +02:00
connect ( inputDevice , & deviceHandler : : frameClosed ,
this , & RadioInterface : : handle_deviceFrame_closed ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( SELECTED_DEVICE , s ) ;
if ( dabSettings_p - > value ( DEVICE_WIDGET_VISIBLE , 1 ) . toInt ( ) ! = 0 )
2024-01-27 20:16:14 +01:00
inputDevice - > setVisibility ( true ) ;
else
inputDevice - > setVisibility ( false ) ;
2024-06-01 11:12:04 +02:00
theNewDisplay . set_bitDepth ( inputDevice - > bitDepth ( ) ) ;
2024-01-27 20:16:14 +01:00
return inputDevice ;
}
//
// newDevice is called from the GUI when selecting a device
// with the selector
void RadioInterface : : newDevice ( const QString & deviceName ) {
// Part I : stopping all activities
running . store ( false ) ;
stopScanning ( ) ;
stopChannel ( ) ;
fprintf ( stderr , " disconnecting \n " ) ;
if ( inputDevice_p ! = nullptr ) {
delete inputDevice_p ;
inputDevice_p = nullptr ;
fprintf ( stderr , " device is deleted \n " ) ;
}
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_NEWDEVICE , deviceName ,
channelSelector - > currentText ( ) ) ;
2024-01-27 20:16:14 +01:00
inputDevice_p = create_device ( deviceName ) ;
2024-02-25 14:18:27 +01:00
fprintf ( stderr , " na create_device met %s \n " , deviceName . toLatin1 ( ) . data ( ) ) ;
2024-01-27 20:16:14 +01:00
if ( inputDevice_p = = nullptr ) {
inputDevice_p = new deviceHandler ( ) ;
return ; // nothing will happen
}
2024-04-14 12:47:14 +02:00
doStart_direct ( ) ; // will set running
2024-01-27 20:16:14 +01:00
}
static
const char * monthTable [ ] = {
" jan " , " feb " , " mar " , " apr " , " may " , " jun " ,
" jul " , " aug " , " sep " , " oct " , " nov " , " dec "
} ;
//
// called from the fibDecoder
void RadioInterface : : clockTime ( int year , int month , int day ,
int hours , int minutes ,
int d2 , int h2 , int m2 , int seconds ) {
this - > localTime . year = year ;
this - > localTime . month = month ;
this - > localTime . day = day ;
this - > localTime . hour = hours ;
this - > localTime . minute = minutes ;
this - > localTime . second = seconds ;
# ifdef CLOCK_STREAMER
uint8_t localBuffer [ 10 ] ;
localBuffer [ 0 ] = 0xFF ;
localBuffer [ 1 ] = 0x00 ;
localBuffer [ 2 ] = 0xFF ;
localBuffer [ 3 ] = 0x00 ;
localBuffer [ 4 ] = ( year & 0xFF00 ) > > 8 ;
localBuffer [ 5 ] = year & 0xFF ;
localBuffer [ 6 ] = month ;
localBuffer [ 7 ] = day ;
localBuffer [ 8 ] = minutes ;
localBuffer [ 9 ] = seconds ;
if ( running . load ( ) )
clockStreamer_p - > sendData ( localBuffer , 10 ) ;
# endif
this - > UTC . year = year ;
this - > UTC . month = month ;
this - > UTC . day = d2 ;
this - > UTC . hour = h2 ;
this - > UTC . minute = m2 ;
QString result ;
2024-02-16 15:46:54 +01:00
if ( configHandler_p - > utcSelector_active ( ) )
2024-01-27 20:16:14 +01:00
result = convertTime ( year , month , day , h2 , m2 ) ;
else
result = convertTime ( year , month , day ,
hours , minutes ) ;
localTimeDisplay - > setText ( result ) ;
}
QString RadioInterface : : convertTime ( int year , int month ,
int day , int hours , int minutes ) {
char dayString [ 3 ] ;
char hourString [ 3 ] ;
char minuteString [ 3 ] ;
sprintf ( dayString , " %.2d " , day ) ;
sprintf ( hourString , " %.2d " , hours ) ;
sprintf ( minuteString , " %.2d " , minutes ) ;
QString result = QString : : number ( year ) + " - " +
monthTable [ month - 1 ] + " - " +
QString ( dayString ) + " " +
QString ( hourString ) + " : " +
QString ( minuteString ) ;
return result ;
}
QString RadioInterface : : convertTime ( struct theTime & t ) {
char dayString [ 3 ] ;
char hourString [ 3 ] ;
char minuteString [ 3 ] ;
sprintf ( dayString , " %.2d " , t . day ) ;
sprintf ( hourString , " %.2d " , t . hour ) ;
sprintf ( minuteString , " %.2d " , t . minute ) ;
QString result = QString : : number ( t . year ) + " - " +
monthTable [ t . month - 1 ] + " - " +
QString ( dayString ) + " " +
QString ( hourString ) + " : " +
QString ( minuteString ) ;
return result ;
}
//
// called from the MP4 decoder
void RadioInterface : : show_frameErrors ( int s ) {
if ( ! running . load ( ) )
return ;
if ( ! techWindow_p - > isHidden ( ) )
techWindow_p - > show_frameErrors ( s ) ;
}
//
// called from the MP4 decoder
void RadioInterface : : show_rsErrors ( int s ) {
if ( ! running . load ( ) ) // should not happen
return ;
if ( ! techWindow_p - > isHidden ( ) )
techWindow_p - > show_rsErrors ( s ) ;
}
//
// called from the aac decoder
void RadioInterface : : show_aacErrors ( int s ) {
if ( ! running . load ( ) )
return ;
if ( ! techWindow_p - > isHidden ( ) )
techWindow_p - > show_aacErrors ( s ) ;
}
//
// called from the ficHandler
void RadioInterface : : show_ficSuccess ( bool b ) {
if ( ! running . load ( ) )
return ;
if ( b )
ficSuccess + + ;
if ( + + ficBlocks > = 100 ) {
2024-06-01 11:12:04 +02:00
QPalette p = theNewDisplay . ficError_display - > palette ( ) ;
2024-01-27 20:16:14 +01:00
if ( ficSuccess < 85 )
p . setColor ( QPalette : : Highlight , Qt : : red ) ;
else
p . setColor ( QPalette : : Highlight , Qt : : green ) ;
2024-06-01 11:12:04 +02:00
theNewDisplay . ficError_display - > setPalette ( p ) ;
theNewDisplay . ficError_display - > setValue ( ficSuccess ) ;
2024-01-27 20:16:14 +01:00
total_ficError + = 100 - ficSuccess ;
total_fics + = 100 ;
ficSuccess = 0 ;
ficBlocks = 0 ;
}
}
//
// called from the PAD handler
void RadioInterface : : show_mothandling ( bool b ) {
if ( ! running . load ( ) | | ! b )
return ;
techWindow_p - > show_motHandling ( b ) ;
}
// just switch a color, called from the dabprocessor
void RadioInterface : : set_synced ( bool b ) {
2024-06-01 11:12:04 +02:00
theNewDisplay . set_syncLabel ( b ) ;
2024-01-27 20:16:14 +01:00
}
//
// called from the PAD handler
void RadioInterface : : show_label ( const QString & s ) {
# ifdef HAVE_PLUTO_RXTX
if ( ( streamerOut_p ! = nullptr ) & & ( s ! = " " ) )
streamerOut_p - > addRds ( std : : string ( s . toUtf8 ( ) . data ( ) ) ) ;
# endif
if ( running . load ( ) ) {
2024-02-06 15:37:07 +01:00
dynamicLabel - > setStyleSheet ( labelStyle ) ;
2024-01-27 20:16:14 +01:00
dynamicLabel - > setText ( s ) ;
}
if ( ( s = = " " ) | | ( dlTextFile = = nullptr ) | |
2024-06-01 11:12:04 +02:00
( theDLCache . addifNew ( s ) ) )
2024-01-27 20:16:14 +01:00
return ;
QString currentChannel = channel . channelName ;
QDateTime theDateTime = QDateTime : : currentDateTime ( ) ;
fprintf ( dlTextFile , " %s.%s %4d-%02d-%02d %02d:%02d:%02d %s \n " ,
currentChannel . toUtf8 ( ) . data ( ) ,
channel . currentService . serviceName .
toUtf8 ( ) . data ( ) ,
localTime . year ,
localTime . month ,
localTime . day ,
localTime . hour ,
localTime . minute ,
localTime . second ,
s . toUtf8 ( ) . data ( ) ) ;
}
void RadioInterface : : setStereo ( bool b ) {
2024-02-25 14:18:27 +01:00
if ( ! running . load ( ) | | ( stereoSetting = = b ) )
2024-01-27 20:16:14 +01:00
return ;
2024-02-06 15:37:07 +01:00
if ( b ) {
stereoLabel - > setStyleSheet ( labelStyle ) ;
stereoLabel - > setText ( " <i>stereo</i> " ) ;
}
else
stereoLabel - > setText ( " " ) ;
2024-01-27 20:16:14 +01:00
stereoSetting = b ;
}
2024-02-25 14:18:27 +01:00
2024-04-10 19:49:55 +02:00
//static
//QString tiiNumber (int n) {
// if (n >= 10)
// return QString::number (n);
// return QString ("0") + QString::number (n);
//}
2024-01-27 20:16:14 +01:00
void RadioInterface : : handle_detailButton ( ) {
if ( ! running . load ( ) )
return ;
if ( techWindow_p - > isHidden ( ) )
techWindow_p - > show ( ) ;
else
techWindow_p - > hide ( ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( TECHDATA_VISIBLE ,
2024-02-16 15:46:54 +01:00
techWindow_p - > isHidden ( ) ? 0 : 1 ) ;
2024-01-27 20:16:14 +01:00
}
//
// Whenever the input device is a file, some functions,
// e.g. selecting a channel, setting an alarm, are not
// meaningful
void RadioInterface : : showButtons ( ) {
scanButton - > setEnabled ( true ) ; ;
channelSelector - > setEnabled ( true ) ;
nextChannelButton - > setEnabled ( true ) ;
prevChannelButton - > setEnabled ( true ) ;
}
void RadioInterface : : hideButtons ( ) {
scanButton - > setEnabled ( false ) ;
channelSelector - > setEnabled ( false ) ;
nextChannelButton - > setEnabled ( false ) ;
prevChannelButton - > setEnabled ( false ) ;
}
void RadioInterface : : set_sync_lost ( ) {
}
//
// dump handling
//
/////////////////////////////////////////////////////////////////////////
2024-02-16 15:46:54 +01:00
static inline
2024-01-27 20:16:14 +01:00
void setButtonFont ( QPushButton * b , QString text , int size ) {
QFont font = b - > font ( ) ;
font . setPointSize ( size ) ;
b - > setFont ( font ) ;
b - > setText ( text ) ;
b - > update ( ) ;
}
void RadioInterface : : handle_audiodumpButton ( ) {
2024-06-01 11:12:04 +02:00
if ( ! running . load ( ) | | theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-07-28 12:47:27 +02:00
if ( audioDumping )
2024-01-27 20:16:14 +01:00
stopAudiodumping ( ) ;
else
startAudiodumping ( ) ;
}
void RadioInterface : : stopAudiodumping ( ) {
2024-07-28 12:47:27 +02:00
if ( ! audioDumping )
2024-01-27 20:16:14 +01:00
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_AUDIODUMP_STOPS ) ;
2024-06-01 11:12:04 +02:00
theAudioConverter . stop_audioDump ( ) ;
2024-07-28 12:47:27 +02:00
audioDumping = false ;
2024-01-27 20:16:14 +01:00
techWindow_p - > audiodumpButton_text ( " audio dump " , 10 ) ;
}
void RadioInterface : : startAudiodumping ( ) {
2024-07-28 12:47:27 +02:00
if ( audioDumping ) // should not happen
return ;
QString audioDumpName =
2024-06-01 11:12:04 +02:00
theFilenameFinder .
2024-01-27 20:16:14 +01:00
findAudioDump_fileName ( channel . currentService . serviceName , true ) ;
2024-07-28 12:47:27 +02:00
if ( audioDumpName = = " " )
2024-01-27 20:16:14 +01:00
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_AUDIODUMP_STARTS ,
channelSelector - > currentText ( ) ,
channel . currentService . serviceName ) ;
2024-01-27 20:16:14 +01:00
techWindow_p - > audiodumpButton_text ( " writing " , 12 ) ;
2024-07-28 12:47:27 +02:00
theAudioConverter . start_audioDump ( audioDumpName ) ;
audioDumping = true ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : scheduled_audioDumping ( ) {
2024-07-28 12:47:27 +02:00
if ( audioDumping ) {
2024-06-01 11:12:04 +02:00
theAudioConverter . stop_audioDump ( ) ;
2024-07-28 12:47:27 +02:00
audioDumping = false ;
2024-01-27 20:16:14 +01:00
techWindow_p - > audiodumpButton_text ( " audio dump " , 10 ) ;
return ;
}
2024-07-28 12:47:27 +02:00
QString audioDumpName =
2024-06-01 11:12:04 +02:00
theFilenameFinder .
2024-01-27 20:16:14 +01:00
findAudioDump_fileName ( serviceLabel - > text ( ) , false ) ;
2024-07-28 12:47:27 +02:00
if ( audioDumpName = = " " )
2024-01-27 20:16:14 +01:00
return ;
techWindow_p - > audiodumpButton_text ( " writing " , 12 ) ;
2024-07-28 12:47:27 +02:00
theAudioConverter . start_audioDump ( audioDumpName ) ;
audioDumping = true ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : handle_framedumpButton ( ) {
2024-06-01 11:12:04 +02:00
if ( ! running . load ( ) | | theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
return ;
if ( channel . currentService . frameDumper ! = nullptr )
stopFramedumping ( ) ;
else
startFramedumping ( ) ;
}
void RadioInterface : : stopFramedumping ( ) {
if ( channel . currentService . frameDumper = = nullptr )
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_FRAMEDUMP_STOPS ) ;
2024-01-27 20:16:14 +01:00
fclose ( channel . currentService . frameDumper ) ;
techWindow_p - > framedumpButton_text ( " frame dump " , 10 ) ;
channel . currentService . frameDumper = nullptr ;
}
void RadioInterface : : startFramedumping ( ) {
channel . currentService . frameDumper =
2024-06-01 11:12:04 +02:00
theFilenameFinder . findFrameDump_fileName ( channel . currentService . serviceName ,
2024-01-27 20:16:14 +01:00
true ) ;
if ( channel . currentService . frameDumper = = nullptr )
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_FRAMEDUMP_STARTS ,
channel . channelName ,
channel . currentService . serviceName ) ;
2024-01-27 20:16:14 +01:00
techWindow_p - > framedumpButton_text ( " recording " , 12 ) ;
}
void RadioInterface : : scheduled_frameDumping ( const QString & s ) {
if ( channel . currentService . frameDumper ! = nullptr ) {
fclose ( channel . currentService . frameDumper ) ;
techWindow_p - > framedumpButton_text ( " frame dump " , 10 ) ;
channel . currentService . frameDumper = nullptr ;
return ;
}
channel . currentService . frameDumper =
2024-06-01 11:12:04 +02:00
theFilenameFinder . findFrameDump_fileName ( s , false ) ;
2024-01-27 20:16:14 +01:00
if ( channel . currentService . frameDumper = = nullptr )
return ;
techWindow_p - > framedumpButton_text ( " recording " , 12 ) ;
}
//----------------------------------------------------------------------
// End of section on dumping
//----------------------------------------------------------------------
//
// called from the mp4 handler, using a signal
void RadioInterface : : newFrame ( int amount ) {
2024-03-13 19:45:53 +01:00
uint8_t * buffer = ( uint8_t * ) alloca ( amount * sizeof ( uint8_t ) ) ;
2024-01-27 20:16:14 +01:00
if ( ! running . load ( ) )
return ;
if ( channel . currentService . frameDumper = = nullptr )
2024-06-01 11:12:04 +02:00
theFrameBuffer . FlushRingBuffer ( ) ;
2024-01-27 20:16:14 +01:00
else
2024-06-01 11:12:04 +02:00
while ( theFrameBuffer . GetRingBufferReadAvailable ( ) > = amount ) {
theFrameBuffer . getDataFromBuffer ( buffer , amount ) ;
2024-01-27 20:16:14 +01:00
if ( channel . currentService . frameDumper ! = nullptr )
fwrite ( buffer , amount , 1 , channel . currentService . frameDumper ) ;
}
}
void RadioInterface : : handle_spectrumButton ( ) {
if ( ! running . load ( ) )
return ;
2024-06-01 11:12:04 +02:00
if ( theNewDisplay . isHidden ( ) )
theNewDisplay . show ( ) ;
2024-01-27 20:16:14 +01:00
else
2024-06-01 11:12:04 +02:00
theNewDisplay . hide ( ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( NEW_DISPLAY_VISIBLE ,
2024-06-01 11:12:04 +02:00
theNewDisplay . isHidden ( ) ? 0 : 1 ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : handle_scanListButton ( ) {
if ( ! running . load ( ) )
return ;
2024-09-04 12:14:53 +02:00
if ( inputDevice_p - > isFileInput ( ) )
return ;
2024-06-01 11:12:04 +02:00
if ( theScanlistHandler . isHidden ( ) )
theScanlistHandler . show ( ) ;
2024-01-27 20:16:14 +01:00
else
2024-06-01 11:12:04 +02:00
theScanlistHandler . hide ( ) ;
2024-01-27 20:16:14 +01:00
}
//
// When changing (or setting) a device, we do not want anybody
// to have the buttons on the GUI touched, so
// we just disconnet them and (re)connect them as soon as
// a device is operational
void RadioInterface : : connectGUI ( ) {
// connections from the main widget
2024-04-14 12:47:14 +02:00
connect ( prevServiceButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_prevServiceButton ) ;
connect ( nextServiceButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_nextServiceButton ) ;
2024-01-27 20:16:14 +01:00
2024-02-16 15:46:54 +01:00
// channelButton handled elsewhere
2024-04-14 12:47:14 +02:00
connect ( prevChannelButton , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_prevChannelButton ) ;
connect ( nextChannelButton , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_nextChannelButton ) ;
2024-01-27 20:16:14 +01:00
2024-04-14 12:47:14 +02:00
connect ( scanListButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_scanListButton ) ;
2024-01-27 20:16:14 +01:00
2024-04-14 12:47:14 +02:00
connect ( presetButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_presetButton ) ;
connect ( spectrumButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_spectrumButton ) ;
connect ( serviceLabel , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_labelColor ) ;
connect ( serviceButton , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_detailButton ) ;
//
connect ( httpButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_httpButton ) ;
connect ( scanButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_scanButton ) ;
2024-01-27 20:16:14 +01:00
//
// and for the techWindow
2024-04-14 12:47:14 +02:00
connect ( techWindow_p , & techData : : handle_audioDumping ,
this , & RadioInterface : : handle_audiodumpButton ) ;
connect ( techWindow_p , & techData : : handle_frameDumping ,
this , & RadioInterface : : handle_framedumpButton ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : disconnectGUI ( ) {
}
//
# include <QCloseEvent>
void RadioInterface : : closeEvent ( QCloseEvent * event ) {
2024-02-16 15:46:54 +01:00
int x = configHandler_p - > closeDirect_active ( ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( CLOSE_DIRECT_SETTING , x ) ;
2024-01-27 20:16:14 +01:00
if ( x ! = 0 ) {
TerminateProcess ( ) ;
event - > accept ( ) ;
return ;
}
QMessageBox : : StandardButton resultButton =
QMessageBox : : question ( this , " dabRadio " ,
tr ( " Are you sure? \n " ) ,
QMessageBox : : No | QMessageBox : : Yes ,
QMessageBox : : Yes ) ;
if ( resultButton ! = QMessageBox : : Yes ) {
event - > ignore ( ) ;
} else {
TerminateProcess ( ) ;
event - > accept ( ) ;
}
}
bool RadioInterface : : eventFilter ( QObject * obj , QEvent * event ) {
if ( ! running . load ( ) )
return QWidget : : eventFilter ( obj , event ) ;
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler = = nullptr ) {
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " expert error 5 \n " ) ;
return true ;
}
else
if ( ( obj = = this - > the_ensembleHandler - > viewport ( ) ) & &
( event - > type ( ) = = QEvent : : MouseButtonPress ) ) {
QMouseEvent * ev = static_cast < QMouseEvent * > ( event ) ;
if ( ev - > buttons ( ) & Qt : : RightButton ) {
QTableWidgetItem * x =
the_ensembleHandler - > itemAt ( ev - > pos ( ) ) ;
if ( x ! = nullptr )
the_ensembleHandler - > handle_rightMouseClick ( x - > text ( ) ) ;
}
else {
return QWidget : : eventFilter ( obj , event ) ;
}
}
else
// An option is to click - right hand mouse button - on a
// service in the scanlist in order to add it to the
// list of favorites
2024-06-01 11:12:04 +02:00
if ( ( obj = = this - > theScanlistHandler . viewport ( ) ) & &
2024-01-27 20:16:14 +01:00
( event - > type ( ) = = QEvent : : MouseButtonPress ) ) {
QMouseEvent * ev = static_cast < QMouseEvent * > ( event ) ;
if ( ev - > buttons ( ) & Qt : : RightButton ) {
QString service =
2024-06-01 11:12:04 +02:00
this - > theScanlistHandler . indexAt ( ev - > pos ( ) ) . data ( ) . toString ( ) ;
2024-01-27 20:16:14 +01:00
the_ensembleHandler - > add_favorite_from_scanList ( service ) ;
}
}
return QWidget : : eventFilter ( obj , event ) ;
}
QPixmap RadioInterface : : fetch_announcement ( int id ) {
QPixmap p ;
QString pictureName = QString ( " :res/announcement%1.png " ) . arg ( id , 2 , 10 , QChar ( ' 0 ' ) ) ;
if ( ! p . load ( pictureName , " png " ) )
p . load ( " :res/announcement-d.png " , " png " ) ;
return p ;
}
void RadioInterface : : start_announcement ( const QString & name ,
int subChId , int announcementId ) {
if ( ! running . load ( ) )
return ;
( void ) subChId ;
if ( name = = serviceLabel - > text ( ) ) {
if ( ! channel . currentService . announcement_going ) {
serviceLabel - > setStyleSheet ( " QLabel {color : red} " ) ;
channel . currentService . announcement_going = true ;
QPixmap p = fetch_announcement ( announcementId ) ;
displaySlide ( p ) ;
}
}
}
void RadioInterface : : stop_announcement ( const QString & name , int subChId ) {
( void ) subChId ;
if ( ! running . load ( ) )
return ;
if ( name = = channel . currentService . serviceName ) {
if ( channel . currentService . announcement_going ) {
2024-02-06 15:37:07 +01:00
serviceLabel - > setStyleSheet ( labelStyle ) ;
2024-01-27 20:16:14 +01:00
channel . currentService . announcement_going = false ;
show_pauzeSlide ( ) ;
}
}
}
//
// selection, either direct, from presets, from scanlist or schedule
////////////////////////////////////////////////////////////////////////
//
// selecting from the preset list
void RadioInterface : : handle_presetSelect ( const QString & channel ,
const QString & service ) {
if ( ! inputDevice_p - > isFileInput ( ) )
2024-04-10 19:49:55 +02:00
localSelect_SS ( service , channel ) ;
2024-01-27 20:16:14 +01:00
else
QMessageBox : : warning ( this , tr ( " Warning " ) ,
tr ( " Selection not possible " ) ) ;
}
//
// selecting from the scan list, which is essential
// the same as handling form the preset list
void RadioInterface : : handle_scanListSelect ( const QString & s ) {
if ( ! inputDevice_p - > isFileInput ( ) )
localSelect ( s ) ;
else
QMessageBox : : warning ( this , tr ( " Warning " ) ,
tr ( " Selection not possible " ) ) ;
}
//
// selecting from a content description
void RadioInterface : : handle_contentSelector ( const QString & s ) {
2024-04-10 19:49:55 +02:00
localSelect_SS ( s , channel . channelName ) ;
2024-01-27 20:16:14 +01:00
}
//
// From a predefined schedule list, the service names most
// likely are less than 16 characters
//
void RadioInterface : : scheduleSelect ( const QString & s ) {
2024-03-13 19:45:53 +01:00
QStringList list = splitter ( s ) ;
2024-01-27 20:16:14 +01:00
if ( list . length ( ) ! = 2 )
return ;
fprintf ( stderr , " we found %s %s \n " ,
list . at ( 1 ) . toLatin1 ( ) . data ( ) ,
list . at ( 0 ) . toLatin1 ( ) . data ( ) ) ;
2024-04-10 19:49:55 +02:00
localSelect_SS ( list . at ( 1 ) , list . at ( 0 ) ) ;
2024-01-27 20:16:14 +01:00
}
//
void RadioInterface : : localSelect ( const QString & s ) {
2024-03-13 19:45:53 +01:00
QStringList list = splitter ( s ) ;
2024-01-27 20:16:14 +01:00
if ( list . length ( ) ! = 2 )
return ;
2024-04-10 19:49:55 +02:00
localSelect_SS ( list . at ( 1 ) , list . at ( 0 ) ) ;
2024-01-27 20:16:14 +01:00
}
2024-04-10 19:49:55 +02:00
void RadioInterface : : localSelect_SS ( const QString & service ,
const QString & theChannel ) {
2024-01-27 20:16:14 +01:00
QString serviceName = service ;
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler = = nullptr ) // should not happen
2024-01-27 20:16:14 +01:00
return ;
2024-03-04 14:45:33 +01:00
channelTimer . stop ( ) ;
2024-03-13 19:45:53 +01:00
presetTimer . stop ( ) ;
2024-01-27 20:16:14 +01:00
stopService ( channel . currentService ) ;
for ( int i = service . size ( ) ; i < 16 ; i + + )
serviceName . push_back ( ' ' ) ;
if ( theChannel = = channel . channelName ) {
channel . currentService . valid = false ;
dabService s ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > get_parameters ( serviceName , & s . SId , & s . SCIds ) ;
2024-01-27 20:16:14 +01:00
if ( s . SId = = 0 ) {
dynamicLabel - > setText ( " cannot run " +
s . serviceName + " yet " ) ;
return ;
}
s . serviceName = serviceName ;
startService ( s ) ;
return ;
}
//
// The hard part is stopping the current service,
// quitting the current channel,
// selecting a new channel, and waiting a while
stopChannel ( ) ;
// and start the new channel first
int k = channelSelector - > findText ( theChannel ) ;
if ( k ! = - 1 ) {
new_channelIndex ( k ) ;
}
else {
QMessageBox : : warning ( this , tr ( " Warning " ) ,
tr ( " Incorrect preset \n " ) ) ;
return ;
}
//
// prepare the service, start the new channel and wait
2024-02-16 15:46:54 +01:00
nextService . valid = true ;
nextService . channel = theChannel ;
nextService . serviceName = serviceName ;
nextService . SId = 0 ;
2024-03-25 14:35:22 +01:00
nextService . SCIds = 0 ;
2024-01-27 20:16:14 +01:00
presetTimer . setSingleShot ( true ) ;
2024-02-16 15:46:54 +01:00
int switchDelay =
configHandler_p - > switchDelayValue ( ) ;
presetTimer . setInterval ( switchDelay ) ;
presetTimer . start ( switchDelay ) ;
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
}
//
///////////////////////////////////////////////////////////////////////////
void RadioInterface : : stopService ( dabService & s ) {
2024-02-16 15:46:54 +01:00
if ( ! s . valid )
return ;
2024-01-27 20:16:14 +01:00
presetTimer . stop ( ) ;
channelTimer . stop ( ) ;
stop_muting ( ) ;
set_soundLabel ( false ) ;
channel . audioActive = false ;
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler = = nullptr ) {
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " Expert error 22 \n " ) ;
return ;
}
// stop "dumpers"
if ( channel . currentService . frameDumper ! = nullptr ) {
stopFramedumping ( ) ;
channel . currentService . frameDumper = nullptr ;
}
2024-07-28 12:47:27 +02:00
if ( audioDumping ) {
2024-01-27 20:16:14 +01:00
stopAudiodumping ( ) ;
}
// and clean up the technical widget
techWindow_p - > cleanUp ( ) ;
// stop "secondary services" - if any - as well
if ( s . valid ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_service ( s . subChId , FORE_GROUND ) ;
2024-01-27 20:16:14 +01:00
if ( s . is_audio ) {
2024-03-13 19:45:53 +01:00
soundOut_p - > suspend ( ) ;
2024-01-27 20:16:14 +01:00
for ( int i = 0 ; i < 5 ; i + + ) {
packetdata pd ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > data_for_packetservice ( s . serviceName ,
2024-07-16 19:52:55 +02:00
pd , i ) ;
2024-01-27 20:16:14 +01:00
if ( pd . defined ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_service ( pd . subchId , FORE_GROUND ) ;
2024-01-27 20:16:14 +01:00
break ;
}
}
}
s . valid = false ;
}
show_pauzeSlide ( ) ;
cleanScreen ( ) ;
}
//
//
void RadioInterface : : startService ( dabService & s ) {
QString serviceName = s . serviceName ;
channel . currentService = s ;
channel . currentService . frameDumper = nullptr ;
channel . currentService . valid = false ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_NEW_SERVICE ,
channelSelector - > currentText ( ) ,
serviceName ) ;
2024-01-27 20:16:14 +01:00
// mark the selected service in the service list
//
// and display the servicename on the serviceLabel
serviceLabel - > setText ( serviceName ) ;
dynamicLabel - > setText ( " " ) ;
the_ensembleHandler - > reportStart ( serviceName ) ;
audiodata ad ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > data_for_audioservice ( serviceName , ad ) ;
2024-01-27 20:16:14 +01:00
if ( ad . defined ) {
channel . currentService . valid = true ;
channel . currentService . is_audio = true ;
channel . currentService . subChId = ad . subchId ;
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler - > has_timeTable ( ad . SId ) )
2024-01-27 20:16:14 +01:00
techWindow_p - > show_timetableButton ( true ) ;
startAudioservice ( ad ) ;
2024-08-18 09:28:40 +02:00
techWindow_p - > is_DAB_plus ( ad . ASCTy = = 077 ) ;
2024-02-25 14:18:27 +01:00
// Only presets for real input devices
if ( ! inputDevice_p - > isFileInput ( ) ) {
2024-01-27 20:16:14 +01:00
QString s = channel . channelName + " : " + serviceName ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( PRESET_NAME , s ) ;
2024-01-27 20:16:14 +01:00
}
# ifdef HAVE_PLUTO_RXTX
if ( streamerOut_p ! = nullptr )
streamerOut_p - > addRds ( std : : string ( serviceName . toUtf8 ( ) . data ( ) ) ) ;
# endif
}
2024-03-27 16:24:49 +01:00
else {
2024-01-27 20:16:14 +01:00
packetdata pd ;
2024-07-16 19:52:55 +02:00
theOFDMHandler - > data_for_packetservice ( serviceName , pd , 0 ) ;
2024-03-27 16:24:49 +01:00
if ( pd . defined ) {
channel . currentService . valid = true ;
channel . currentService . is_audio = false ;
channel . currentService . subChId = pd . subchId ;
startPacketservice ( serviceName ) ;
}
else {
QMessageBox : : warning ( this , tr ( " Warning " ) ,
tr ( " insufficient data for this program \n " ) ) ;
dabSettings_p - > setValue ( PRESET_NAME , " " ) ;
}
2024-01-27 20:16:14 +01:00
}
}
//
void RadioInterface : : startAudioservice ( audiodata & ad ) {
2024-03-04 14:45:33 +01:00
// channel. currentService. valid = true;
2024-06-01 11:12:04 +02:00
( void ) theOFDMHandler - > set_audioChannel ( ad , & theAudioBuffer ,
2024-01-27 20:16:14 +01:00
nullptr , FORE_GROUND ) ;
2024-03-25 14:35:22 +01:00
//
// check the other components for this service (if any)
int nrComps =
2024-06-01 11:12:04 +02:00
theOFDMHandler - > get_nrComps ( channel . currentService . SId ) ;
2024-03-25 14:35:22 +01:00
for ( int i = 1 ; i < nrComps ; i + + ) {
2024-01-27 20:16:14 +01:00
packetdata pd ;
2024-07-16 19:52:55 +02:00
theOFDMHandler - > data_for_packetservice ( ad . serviceName , pd , i ) ;
2024-01-27 20:16:14 +01:00
if ( pd . defined ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_dataChannel ( pd , & theDataBuffer , FORE_GROUND ) ;
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " adding %s (%d) as subservice \n " ,
pd . serviceName . toUtf8 ( ) . data ( ) ,
pd . subchId ) ;
break ;
}
}
// activate sound
2024-03-13 19:45:53 +01:00
soundOut_p - > resume ( ) ;
2024-01-27 20:16:14 +01:00
channel . audioActive = true ;
set_soundLabel ( true ) ;
2024-02-06 15:37:07 +01:00
programTypeLabel - > setText ( getProgramType ( ad . programType ) ) ;
rateLabel - > setStyleSheet ( labelStyle ) ;
rateLabel - > setText ( QString : : number ( ad . bitRate ) + " kbit " ) ;
2024-01-27 20:16:14 +01:00
// show service related data
techWindow_p - > show_serviceData ( & ad ) ;
}
void RadioInterface : : startPacketservice ( const QString & s ) {
packetdata pd ;
2024-07-16 19:52:55 +02:00
theOFDMHandler - > data_for_packetservice ( s , pd , 0 ) ;
2024-01-27 20:16:14 +01:00
if ( ( ! pd . defined ) | |
( pd . DSCTy = = 0 ) | | ( pd . bitRate = = 0 ) ) {
QMessageBox : : warning ( this , tr ( " sdr " ) ,
tr ( " still insufficient data for this service \n " ) ) ;
return ;
}
2024-06-01 11:12:04 +02:00
if ( ! theOFDMHandler - > set_dataChannel ( pd ,
& theDataBuffer , FORE_GROUND ) ) {
2024-01-27 20:16:14 +01:00
QMessageBox : : warning ( this , tr ( " sdr " ) ,
tr ( " could not start this service \n " ) ) ;
return ;
}
2024-03-27 16:24:49 +01:00
int nrComps =
2024-06-01 11:12:04 +02:00
theOFDMHandler - > get_nrComps ( channel . currentService . SId ) ;
2024-03-27 16:24:49 +01:00
if ( nrComps > 1 )
fprintf ( stderr , " %s has %d components \b " ,
channel . currentService . serviceName . toLatin1 ( ) . data ( ) , nrComps ) ;
for ( int i = 1 ; i < nrComps ; i + + ) {
packetdata lpd ;
2024-07-16 19:52:55 +02:00
theOFDMHandler - > data_for_packetservice ( pd . serviceName , lpd , i ) ;
2024-03-27 16:24:49 +01:00
if ( lpd . defined ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_dataChannel ( lpd , & theDataBuffer , FORE_GROUND ) ;
2024-03-27 16:24:49 +01:00
fprintf ( stderr , " adding %s (%d) as subservice \n " ,
lpd . serviceName . toUtf8 ( ) . data ( ) ,
lpd . subchId ) ;
break ;
}
}
2024-01-27 20:16:14 +01:00
switch ( pd . DSCTy ) {
default :
show_label ( QString ( " unimplemented Data " ) ) ;
break ;
case 5 :
fprintf ( stderr , " selected apptype %d \n " , pd . appType ) ;
2024-09-18 12:08:40 +02:00
show_label ( QString ( " Transp. Channel partially implemented " ) ) ;
2024-01-27 20:16:14 +01:00
break ;
case 60 :
2024-09-18 12:08:40 +02:00
show_label ( QString ( " MOT " ) ) ;
2024-01-27 20:16:14 +01:00
break ;
case 59 : {
# ifdef _SEND_DATAGRAM_
QString text = QString ( " Embedded IP: UDP data to " ) ;
text . append ( ipAddress ) ;
text . append ( " " ) ;
QString n = QString : : number ( port ) ;
text . append ( n ) ;
show_label ( text ) ;
# else
show_label ( " Embedded IP not supported " ) ;
# endif
}
break ;
case 44 :
show_label ( QString ( " Journaline " ) ) ;
break ;
}
}
// This function is only used in the Gui to clear
// the details of a selected service
void RadioInterface : : cleanScreen ( ) {
serviceLabel - > setText ( " " ) ;
dynamicLabel - > setText ( " " ) ;
techWindow_p - > cleanUp ( ) ;
stereoLabel - > setText ( " " ) ;
programTypeLabel - > setText ( " " ) ;
psLabel - > setText ( " " ) ;
sbrLabel - > setText ( " " ) ;
audiorateLabel - > setText ( " " ) ;
rateLabel - > setText ( " " ) ;
stereoLabel - > setText ( " " ) ;
stereoSetting = false ;
techWindow_p - > cleanUp ( ) ;
setStereo ( false ) ;
2024-02-16 15:46:54 +01:00
distanceLabel - > setText ( " " ) ;
transmitter_country - > setText ( " " ) ;
2024-06-01 11:12:04 +02:00
theNewDisplay . ficError_display - > setValue ( 0 ) ;
2024-01-27 20:16:14 +01:00
}
////////////////////////////////////////////////////////////////////////////
//
void RadioInterface : : handle_prevServiceButton ( ) {
the_ensembleHandler - > selectPrevService ( ) ;
}
void RadioInterface : : handle_nextServiceButton ( ) {
the_ensembleHandler - > selectNextService ( ) ;
}
//
// The user(s)
///////////////////////////////////////////////////////////////////////////
// setPresetService () is called after a time out to
// actually start the service that we were waiting for
// Assumption is that the channel is set, and the servicename
// is to be found in "nextService"
void RadioInterface : : setPresetService ( ) {
if ( ! running . load ( ) )
return ;
stopScanning ( ) ;
2024-03-04 14:45:33 +01:00
presetTimer . stop ( ) ;
2024-02-16 15:46:54 +01:00
if ( ! nextService . valid )
2024-01-27 20:16:14 +01:00
return ;
2024-02-16 15:46:54 +01:00
if ( nextService . channel ! = channel . channelName )
2024-01-27 20:16:14 +01:00
return ;
if ( channel . Eid = = 0 ) {
dynamicLabel - > setText ( " ensemblename not yet found \n " ) ;
return ;
}
2024-02-16 15:46:54 +01:00
QString presetName = nextService . serviceName ;
2024-01-27 20:16:14 +01:00
for ( int i = presetName . length ( ) ; i < 16 ; i + + )
presetName . push_back ( ' ' ) ;
2024-02-16 15:46:54 +01:00
dabService s = nextService ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > get_parameters ( presetName , & s . SId , & s . SCIds ) ;
2024-01-27 20:16:14 +01:00
if ( s . SId = = 0 ) {
dynamicLabel - > setText ( QString ( " not all data for " ) +
s . serviceName +
" on board " ) ;
return ;
}
2024-02-16 15:46:54 +01:00
nextService . valid = false ;
2024-01-27 20:16:14 +01:00
startService ( s ) ;
}
//
// Channel basics
///////////////////////////////////////////////////////////////////////////
// Precondition: no channel should be active
//
void RadioInterface : : startChannel ( const QString & theChannel ) {
int tunedFrequency =
2024-06-01 11:12:04 +02:00
theSCANHandler . Frequency ( theChannel ) ;
2024-09-04 12:14:53 +02:00
theNewDisplay . showFrequency ( theChannel , tunedFrequency ) ;
2024-01-27 20:16:14 +01:00
inputDevice_p - > restartReader ( tunedFrequency ) ;
channel . cleanChannel ( ) ;
channel . channelName = theChannel ;
channel . tunedFrequency = tunedFrequency ;
2024-09-04 09:46:23 +02:00
channel . countryName = " " ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_NEW_CHANNEL , theChannel , channel . snr ) ;
2024-07-27 15:30:56 +02:00
if ( inputDevice_p - > isFileInput ( ) ) {
channelSelector - > setEnabled ( false ) ;
int freq = inputDevice_p - > getVFOFrequency ( ) ;
QString realChannel = theSCANHandler . getChannel ( freq ) ;
if ( realChannel ! = " " ) {
int k = channelSelector - > findText ( realChannel ) ;
channelSelector - > setCurrentIndex ( k ) ;
channel . channelName = realChannel ;
channel . tunedFrequency = freq ;
2024-09-04 12:14:53 +02:00
theNewDisplay . showFrequency ( realChannel ,
channel . tunedFrequency ) ;
2024-07-27 15:30:56 +02:00
}
else {
channel . channelName = " " ;
channel . tunedFrequency = - 1 ;
}
}
2024-01-27 20:16:14 +01:00
channel . realChannel = ! inputDevice_p - > isFileInput ( ) ;
2024-03-04 14:45:33 +01:00
if ( channel . realChannel )
dabSettings_p - > setValue ( CHANNEL_NAME , theChannel ) ;
2024-01-27 20:16:14 +01:00
distanceLabel - > setText ( " " ) ;
2024-06-01 11:12:04 +02:00
theDXDisplay . cleanUp ( ) ;
theNewDisplay . show_transmitters ( channel . transmitters ) ;
2024-02-16 15:46:54 +01:00
bool localTransmitters =
configHandler_p - > localTransmitterSelector_active ( ) ;
if ( localTransmitters & & ( mapHandler ! = nullptr ) )
2024-02-25 14:18:27 +01:00
mapHandler - > putData ( MAP_RESET , channel . targetPos ) ;
2024-01-27 20:16:14 +01:00
else
if ( mapHandler ! = nullptr )
2024-02-25 14:18:27 +01:00
mapHandler - > putData ( MAP_FRAME , position { - 1 , - 1 } ) ;
2024-03-04 14:45:33 +01:00
the_ensembleHandler - > reset ( ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > start ( ) ;
2024-02-16 15:46:54 +01:00
int switchDelay = configHandler_p - > switchDelayValue ( ) ;
2024-06-01 11:12:04 +02:00
if ( ! theSCANHandler . active ( ) )
2024-02-16 15:46:54 +01:00
epgTimer . start ( switchDelay ) ;
2024-01-27 20:16:14 +01:00
}
//
// apart from stopping the reader, a lot of administration
// is to be done.
void RadioInterface : : stopChannel ( ) {
if ( inputDevice_p = = nullptr ) // should not happen
return ;
2024-02-16 15:46:54 +01:00
epgTimer . stop ( ) ; // if running
presetTimer . stop ( ) ; // if running
channelTimer . stop ( ) ; // if running
inputDevice_p - > stopReader ( ) ;
2024-04-14 12:47:14 +02:00
disconnect ( ensembleId , & clickablelabel : : clicked ,
this , & RadioInterface : : handle_contentButton ) ;
2024-02-16 15:46:54 +01:00
ensembleId - > setText ( " " ) ;
stop_sourcedumping ( ) ;
2024-03-04 14:45:33 +01:00
stop_etiHandler ( ) ; // if any
2024-10-14 13:12:03 +02:00
// LOG channel exit
2024-08-27 12:40:14 +02:00
transmitter_country - > setText ( " " ) ;
2024-01-27 20:16:14 +01:00
//
// first, stop services in fore and background
if ( channel . currentService . valid )
stopService ( channel . currentService ) ;
2024-03-13 19:45:53 +01:00
soundOut_p - > suspend ( ) ;
2024-01-27 20:16:14 +01:00
2024-02-25 14:18:27 +01:00
for ( auto s : channel . backgroundServices ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_service ( s . subChId , BACK_GROUND ) ;
2024-01-27 20:16:14 +01:00
if ( s . fd ! = nullptr )
fclose ( s . fd ) ;
}
channel . backgroundServices . clear ( ) ;
2024-02-16 15:46:54 +01:00
2024-01-27 20:16:14 +01:00
if ( contentTable_p ! = nullptr ) {
contentTable_p - > hide ( ) ;
delete contentTable_p ;
contentTable_p = nullptr ;
}
// note framedumping - if any - was already stopped
// ficDumping - if on - is stopped here
if ( ficDumpPointer ! = nullptr ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_ficDump ( ) ;
2024-01-27 20:16:14 +01:00
ficDumpPointer = nullptr ;
}
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop ( ) ;
theDXDisplay . cleanUp ( ) ;
2024-01-27 20:16:14 +01:00
usleep ( 1000 ) ;
techWindow_p - > cleanUp ( ) ;
show_pauzeSlide ( ) ;
channel . cleanChannel ( ) ;
2024-02-16 15:46:54 +01:00
bool localTransmitters =
configHandler_p - > localTransmitterSelector_active ( ) ;
if ( localTransmitters & & ( mapHandler ! = nullptr ) )
2024-02-25 14:18:27 +01:00
mapHandler - > putData ( MAP_RESET , channel . targetPos ) ;
2024-01-27 20:16:14 +01:00
QCoreApplication : : processEvents ( ) ;
//
// no processing left at this time
usleep ( 1000 ) ; // may be handling pending signals?
// all stopped, now look at the GUI elements
// the visual elements related to service and channel
set_synced ( false ) ;
cleanScreen ( ) ;
}
//
// next- and previous channel buttons
/////////////////////////////////////////////////////////////////////////
void RadioInterface : : handle_channelSelector ( const QString & channel ) {
if ( ! running . load ( ) )
return ;
2024-10-14 13:12:03 +02:00
// LOG select channel
2024-01-27 20:16:14 +01:00
presetTimer . stop ( ) ;
stopScanning ( ) ;
stopChannel ( ) ;
startChannel ( channel ) ;
}
void RadioInterface : : handle_nextChannelButton ( ) {
int nrChannels = channelSelector - > count ( ) ;
int newChannel = channelSelector - > currentIndex ( ) + 1 ;
set_channelButton ( newChannel % nrChannels ) ;
}
void RadioInterface : : handle_prevChannelButton ( ) {
int nrChannels = channelSelector - > count ( ) ;
if ( channelSelector - > currentIndex ( ) = = 0 )
set_channelButton ( nrChannels - 1 ) ;
else
set_channelButton ( channelSelector - > currentIndex ( ) - 1 ) ;
}
void RadioInterface : : set_channelButton ( int currentChannel ) {
if ( ! running . load ( ) )
return ;
presetTimer . stop ( ) ;
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler = = nullptr ) {
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " Expert error 23 \n " ) ;
abort ( ) ;
}
stopScanning ( ) ;
stopChannel ( ) ;
new_channelIndex ( currentChannel ) ;
startChannel ( channelSelector - > currentText ( ) ) ;
}
//
// scanning
// The scan function covers three scan strategies. In order to make things
// manageable, we implement the streams in different functions and procedures
void RadioInterface : : handle_scanButton ( ) {
if ( ! running . load ( ) )
return ;
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . isVisible ( ) )
theSCANHandler . hide ( ) ;
2024-01-27 20:16:14 +01:00
else
2024-06-01 11:12:04 +02:00
theSCANHandler . show ( ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : startScanning ( ) {
2024-02-01 11:39:22 +01:00
the_ensembleHandler - > set_showMode ( SHOW_ENSEMBLE ) ;
presetButton - > setText ( " not in use " ) ;
presetButton - > setEnabled ( false ) ;
2024-01-27 20:16:14 +01:00
stopChannel ( ) ;
presetTimer . stop ( ) ;
channelTimer . stop ( ) ;
if ( inputDevice_p - > isFileInput ( ) )
QMessageBox : : warning ( this , tr ( " Warning " ) ,
tr ( " Scanning not useful with file input " ) ) ;
epgTimer . stop ( ) ;
2024-06-01 11:12:04 +02:00
connect ( theOFDMHandler , & ofdmHandler : : no_signal_found ,
2024-04-14 12:47:14 +02:00
this , & RadioInterface : : no_signal_found ) ;
2024-01-27 20:16:14 +01:00
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . scan_to_data ( ) )
2024-01-27 20:16:14 +01:00
start_scan_to_data ( ) ;
else
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . scan_single ( ) )
2024-01-27 20:16:14 +01:00
start_scan_single ( ) ;
else
start_scan_continuous ( ) ;
}
void RadioInterface : : start_scan_to_data ( ) {
// when running scan to data, we look at all channels, whether
// on the skiplist or not
2024-06-01 11:12:04 +02:00
QString cs = theSCANHandler . getNextChannel ( channelSelector - > currentText ( ) ) ;
2024-01-27 20:16:14 +01:00
int cc = channelSelector - > findText ( cs ) ;
2024-10-14 13:12:03 +02:00
// LOG scanning starts
2024-01-27 20:16:14 +01:00
new_channelIndex ( cc ) ;
2024-06-01 11:12:04 +02:00
// theSCANHandler. addText (" scanning channel " +
2024-01-27 20:16:14 +01:00
// channelSelector -> currentText ());
int switchDelay =
2024-02-16 15:46:54 +01:00
configHandler_p - > switchDelayValue ( ) ;
channelTimer . start ( switchDelay ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_scanMode ( true ) ;
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
}
void RadioInterface : : start_scan_single ( ) {
2024-02-16 15:46:54 +01:00
if ( configHandler_p - > clearScan_Selector_active ( ) )
2024-06-01 11:12:04 +02:00
theScanlistHandler . clear_scanList ( ) ;
2024-01-27 20:16:14 +01:00
if ( scanTable_p = = nullptr )
scanTable_p = new contentTable ( this , dabSettings_p , " scan " ,
2024-06-01 11:12:04 +02:00
theOFDMHandler - > scanWidth ( ) ) ;
2024-01-27 20:16:14 +01:00
else // should not happen
scanTable_p - > clearTable ( ) ;
QString topLine = QString ( " ensemble " ) + " ; " +
" channelName " + " ; " +
" frequency (KHz) " + " ; " +
" Eid " + " ; " +
" tii " + " ; " +
" time " + " ; " +
" SNR " + " ; " +
" nr services " + " ; " ;
2024-03-04 14:45:33 +01:00
scanTable_p - > addLine ( topLine ) ;
2024-01-27 20:16:14 +01:00
scanTable_p - > addLine ( " \n " ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_scanMode ( true ) ;
QString fs = theSCANHandler . getFirstChannel ( ) ;
2024-01-27 20:16:14 +01:00
int k = channelSelector - > findText ( fs ) ;
if ( k ! = - 1 )
new_channelIndex ( k ) ;
2024-06-01 11:12:04 +02:00
theSCANHandler . addText ( " scanning channel " +
2024-03-04 14:45:33 +01:00
channelSelector - > currentText ( ) ) ;
2024-01-27 20:16:14 +01:00
int switchDelay =
2024-02-16 15:46:54 +01:00
configHandler_p - > switchDelayValue ( ) ;
channelTimer . start ( switchDelay ) ;
2024-03-04 14:45:33 +01:00
fprintf ( stderr , " en starten maar \n " ) ;
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
}
void RadioInterface : : start_scan_continuous ( ) {
if ( scanTable_p = = nullptr )
scanTable_p = new contentTable ( this , dabSettings_p , " scan " ,
2024-06-01 11:12:04 +02:00
theOFDMHandler - > scanWidth ( ) ) ;
2024-01-27 20:16:14 +01:00
else // should not happen
scanTable_p - > clearTable ( ) ;
QString topLine = QString ( " ensemble " ) + " ; " +
" channelName " + " ; " +
" frequency (KHz) " + " ; " +
" Eid " + " ; " +
" tii " + " ; " +
" time " + " ; " +
" SNR " + " ; " +
" nr services " + " ; " ;
scanTable_p - > addLine ( topLine ) ;
scanTable_p - > addLine ( " \n " ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_scanMode ( true ) ;
2024-01-27 20:16:14 +01:00
// To avoid reaction of the system on setting a different value:
2024-06-01 11:12:04 +02:00
QString fs = theSCANHandler . getFirstChannel ( ) ;
2024-01-27 20:16:14 +01:00
int k = channelSelector - > findText ( fs ) ;
new_channelIndex ( k ) ;
int switchDelay =
2024-02-16 15:46:54 +01:00
configHandler_p - > switchDelayValue ( ) ;
2024-04-10 19:49:55 +02:00
channelTimer . start ( 2 * switchDelay ) ;
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
}
//
// stop_scanning is called
// 1. when the scanbutton is touched during scanning
// 2. on user selection of a service or a channel select
// 3. on device selection
// 4. on handling a reset
void RadioInterface : : stopScanning ( ) {
2024-06-01 11:12:04 +02:00
disconnect ( theOFDMHandler , & ofdmHandler : : no_signal_found ,
2024-04-14 12:47:14 +02:00
this , & RadioInterface : : no_signal_found ) ;
2024-06-01 11:12:04 +02:00
if ( ! theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-02-01 11:39:22 +01:00
presetButton - > setText ( " favorites " ) ;
presetButton - > setEnabled ( true ) ;
2024-10-14 13:12:03 +02:00
// LOG scanning stops
2024-03-04 14:45:33 +01:00
channelTimer . stop ( ) ;
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . scan_to_data ( ) )
2024-01-27 20:16:14 +01:00
stop_scan_to_data ( ) ;
else
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . scan_single ( ) )
2024-01-27 20:16:14 +01:00
stop_scan_single ( ) ;
else
stop_scan_continuous ( ) ;
2024-06-01 11:12:04 +02:00
theSCANHandler . setStop ( ) ;
2024-01-27 20:16:14 +01:00
// presetButton -> setEnabled (true);
}
void RadioInterface : : stop_scan_to_data ( ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_scanMode ( false ) ;
2024-01-27 20:16:14 +01:00
channelTimer . stop ( ) ;
}
void RadioInterface : : stop_scan_single ( ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_scanMode ( false ) ;
2024-01-27 20:16:14 +01:00
channelTimer . stop ( ) ;
if ( scanTable_p = = nullptr )
return ; // should not happen
2024-03-04 14:45:33 +01:00
if ( configHandler_p - > upload_selector_active ( ) ) {
2024-03-13 19:45:53 +01:00
try {
uploader the_uploader ;
QMessageBox : : StandardButton reply =
2024-03-04 14:45:33 +01:00
QMessageBox : : question ( this ,
2024-03-13 19:45:53 +01:00
" upload content to fmlist.org? " , " " ,
2024-03-04 14:45:33 +01:00
QMessageBox : : Yes | QMessageBox : : No ) ;
2024-03-13 19:45:53 +01:00
if ( reply = = QMessageBox : : Yes ) {
the_uploader . loadUp ( " Scan " ,
0 ,
" result table " ,
scanTable_p - > upload ( ) ) ;
}
} catch ( . . . ) { }
2024-03-04 14:45:33 +01:00
}
2024-06-01 11:12:04 +02:00
FILE * scanDumper_p = theSCANHandler . askFileName ( ) ;
2024-01-27 20:16:14 +01:00
if ( scanDumper_p ! = nullptr ) {
scanTable_p - > dump ( scanDumper_p ) ;
fclose ( scanDumper_p ) ;
scanDumper_p = nullptr ;
}
delete scanTable_p ;
scanTable_p = nullptr ;
}
void RadioInterface : : stop_scan_continuous ( ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_scanMode ( false ) ;
2024-01-27 20:16:14 +01:00
channelTimer . stop ( ) ;
if ( scanTable_p = = nullptr )
return ; // should not happen
2024-06-01 11:12:04 +02:00
FILE * scanDumper_p = theSCANHandler . askFileName ( ) ;
2024-01-27 20:16:14 +01:00
if ( scanDumper_p ! = nullptr ) {
scanTable_p - > dump ( scanDumper_p ) ;
fclose ( scanDumper_p ) ;
scanDumper_p = nullptr ;
}
delete scanTable_p ;
scanTable_p = nullptr ;
}
// If the ofdm processor has waited - without success -
// for a period of N frames to get a start of a synchronization,
// it sends a signal to the GUI handler
// If "scanning" is "on" we hop to the next frequency on
// the list.
// Also called as a result of time out on channelTimer
2024-03-04 14:45:33 +01:00
void RadioInterface : : channel_timeOut ( ) {
2024-01-27 20:16:14 +01:00
channelTimer . stop ( ) ;
2024-06-01 11:12:04 +02:00
if ( ! theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . scan_to_data ( ) )
2024-01-27 20:16:14 +01:00
next_for_scan_to_data ( ) ;
else
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . scan_single ( ) )
2024-01-27 20:16:14 +01:00
next_for_scan_single ( ) ;
else
next_for_scan_continuous ( ) ;
}
void RadioInterface : : next_for_scan_to_data ( ) {
if ( channel . nrServices > 0 ) {
stopScanning ( ) ;
return ;
}
stopChannel ( ) ;
2024-06-01 11:12:04 +02:00
QString ns = theSCANHandler . getNextChannel ( ) ;
2024-01-27 20:16:14 +01:00
int cc = channelSelector - > findText ( ns ) ;
new_channelIndex ( cc ) ;
//
// and restart for the next run
2024-06-01 11:12:04 +02:00
theSCANHandler . addText ( " scanning channel " +
2024-03-04 14:45:33 +01:00
channelSelector - > currentText ( ) ) ;
2024-01-27 20:16:14 +01:00
int switchDelay =
2024-02-16 15:46:54 +01:00
configHandler_p - > switchDelayValue ( ) ;
channelTimer . start ( switchDelay ) ;
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
}
void RadioInterface : : next_for_scan_single ( ) {
if ( channel . nrServices > 0 )
show_for_single_scan ( ) ;
stopChannel ( ) ;
try {
2024-06-01 11:12:04 +02:00
QString cs = theSCANHandler . getNextChannel ( ) ;
2024-01-27 20:16:14 +01:00
int cc = channelSelector - > findText ( cs ) ;
new_channelIndex ( cc ) ;
} catch ( . . . ) {
stopScanning ( ) ;
return ;
}
2024-06-01 11:12:04 +02:00
theSCANHandler . addText ( " scanning channel " +
2024-03-04 14:45:33 +01:00
channelSelector - > currentText ( ) ) ;
2024-01-27 20:16:14 +01:00
int switchDelay =
2024-02-16 15:46:54 +01:00
configHandler_p - > switchDelayValue ( ) ;
channelTimer . start ( switchDelay ) ;
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
}
void RadioInterface : : next_for_scan_continuous ( ) {
if ( channel . nrServices > 0 )
show_for_continuous ( ) ;
stopChannel ( ) ;
2024-06-01 11:12:04 +02:00
QString cs = theSCANHandler . getNextChannel ( ) ;
2024-01-27 20:16:14 +01:00
int cc = channelSelector - > findText ( cs ) ;
new_channelIndex ( cc ) ;
int switchDelay =
2024-02-16 15:46:54 +01:00
configHandler_p - > switchDelayValue ( ) ;
2024-04-10 19:49:55 +02:00
channelTimer . start ( 2 * switchDelay ) ;
2024-01-27 20:16:14 +01:00
startChannel ( channelSelector - > currentText ( ) ) ;
}
////////////////////////////////////////////////////////////////////////////
2024-04-07 14:58:26 +02:00
QString RadioInterface : : build_headLine ( ) {
2024-01-27 20:16:14 +01:00
QString SNR = " SNR " + QString : : number ( channel . snr ) ;
2024-04-07 14:58:26 +02:00
QString tii ;
QString theName ;
QString theDistance ;
QString theCorner ;
QString theHeight ;
2024-01-27 20:16:14 +01:00
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler = = nullptr ) { // cannot happen
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " Expert error 26 \n " ) ;
2024-04-07 14:58:26 +02:00
return " " ;
2024-01-27 20:16:14 +01:00
}
2024-04-08 11:08:56 +02:00
if ( channel . mainId ! = - 1 )
2024-04-07 14:58:26 +02:00
tii = ids_to_string ( channel . mainId ,
channel . subId ) + " ; " ;
2024-04-08 11:08:56 +02:00
else
tii = " ?,?; " ;
2024-04-10 19:49:55 +02:00
if ( channel . transmitterName ! = " " )
2024-04-07 14:58:26 +02:00
theName = channel . transmitterName + " ; " ;
2024-04-08 11:08:56 +02:00
else
theName = " ; " ;
2024-04-10 19:49:55 +02:00
if ( channel . distance > 0 ) {
2024-04-07 14:58:26 +02:00
theDistance = QString : : number ( channel . distance , ' f ' , 1 ) + " km " ;
theCorner = QString : : number ( channel . corner , ' f ' , 1 )
+ QString : : fromLatin1 ( " \xb0 " ) ;
theHeight = " ( " + QString : : number ( channel . height , ' f ' , 1 ) + " m) " + " \n " ;
}
else {
theDistance = " unknown " ;
theCorner = " " ;
theHeight = " \n " ;
}
2024-01-27 20:16:14 +01:00
QString utcTime = convertTime ( UTC . year , UTC . month ,
UTC . day , UTC . hour ,
UTC . minute ) ;
QString headLine = channel . ensembleName + " ; " +
2024-04-07 14:58:26 +02:00
channel . channelName + " ; " +
2024-01-27 20:16:14 +01:00
QString : : number ( channel . tunedFrequency ) + " ; " +
2024-04-07 14:58:26 +02:00
hextoString ( channel . Eid ) + " ; " +
tii +
utcTime + " ; " +
SNR + " ; " +
QString : : number ( channel . nrServices ) + " ; " +
theName + theDistance + theCorner + theHeight ;
return headLine ;
}
2024-04-03 18:44:52 +02:00
2024-04-07 14:58:26 +02:00
void RadioInterface : : show_for_single_scan ( ) {
QString headLine = build_headLine ( ) ;
2024-06-01 11:12:04 +02:00
QStringList s = theOFDMHandler - > basicPrint ( ) ;
2024-01-27 20:16:14 +01:00
scanTable_p - > addLine ( headLine ) ;
scanTable_p - > addLine ( " \n ; \n " ) ;
for ( const auto & l : s )
scanTable_p - > addLine ( l ) ;
scanTable_p - > addLine ( " \n ; \n ; \n " ) ;
scanTable_p - > show ( ) ;
}
void RadioInterface : : show_for_continuous ( ) {
2024-04-10 19:49:55 +02:00
QString headLine = build_headLine ( ) ;
2024-01-27 20:16:14 +01:00
scanTable_p - > addLine ( headLine ) ;
2024-04-10 19:49:55 +02:00
for ( auto & tr : channel . transmitters ) {
if ( ! tr . isStrongest ) {
QString line = build_cont_addLine ( tr ) ;
if ( line = = " " )
continue ;
scanTable_p - > addLine ( line ) ;
}
}
scanTable_p - > show ( ) ;
}
QString RadioInterface : : build_cont_addLine ( transmitterDesc & tr ) {
QString tii ;
QString theName ;
QString theDistance ;
QString theCorner ;
QString theHeight ;
tii = ids_to_string ( tr . theTransmitter . mainId ,
tr . theTransmitter . subId ) + " ; " ;
if ( tr . theTransmitter . transmitterName ! = " " )
theName = tr . theTransmitter . transmitterName + " ; " ;
else
theName = " ; " ;
if ( tr . distance > 0 ) {
theDistance = QString : : number ( tr . distance , ' f ' , 1 ) + " km " ;
theCorner = QString : : number ( tr . corner , ' f ' , 1 )
+ QString : : fromLatin1 ( " \xb0 " ) ;
theHeight = " ( " + QString : : number ( tr . theTransmitter . height , ' f ' , 1 ) + " m) " + " \n " ;
}
else {
theDistance = " unknown " ;
theCorner = " ? " ;
theHeight = " ? " ;
}
return QString ( " ; " ) +
" ; " +
" ; " +
" ; " +
tii +
" ; " +
" ; " +
" ; " +
theName + theDistance + theCorner + theHeight ;
2024-01-27 20:16:14 +01:00
}
/////////////////////////////////////////////////////////////////////
//
// Handling the Mute button
void RadioInterface : : handle_muteButton ( ) {
if ( muteTimer . isActive ( ) ) {
stop_muting ( ) ;
return ;
}
if ( ! channel . audioActive )
return ;
set_soundLabel ( false ) ;
2024-04-14 12:47:14 +02:00
connect ( & muteTimer , & QTimer : : timeout ,
this , & RadioInterface : : muteButton_timeOut ) ;
2024-02-16 15:46:54 +01:00
muteDelay = configHandler_p - > muteValue ( ) ;
2024-02-27 15:03:33 +01:00
muteDelay * = 60 ; // seconds
2024-01-27 20:16:14 +01:00
muteTimer . start ( 1000 ) ;
stillMuting - > show ( ) ;
stillMuting - > display ( muteDelay ) ;
}
void RadioInterface : : muteButton_timeOut ( ) {
muteDelay - - ;
if ( muteDelay > 0 ) {
stillMuting - > display ( muteDelay ) ;
muteTimer . start ( 1000 ) ;
return ;
}
else {
2024-04-14 12:47:14 +02:00
disconnect ( & muteTimer , & QTimer : : timeout ,
this , & RadioInterface : : muteButton_timeOut ) ;
2024-01-27 20:16:14 +01:00
stillMuting - > hide ( ) ;
2024-03-18 19:06:37 +01:00
if ( channel . audioActive )
2024-01-27 20:16:14 +01:00
set_soundLabel ( true ) ;
}
}
void RadioInterface : : stop_muting ( ) {
if ( ! muteTimer . isActive ( ) )
return ;
set_soundLabel ( true ) ;
muteTimer . stop ( ) ;
2024-04-14 12:47:14 +02:00
disconnect ( & muteTimer , & QTimer : : timeout ,
this , & RadioInterface : : muteButton_timeOut ) ;
2024-01-27 20:16:14 +01:00
stillMuting - > hide ( ) ;
}
//
// End of handling mute button
2024-02-27 15:03:33 +01:00
// new_channelIndex is called whenever we are sure that
// the channel selector is "connected", and we programamtically
// change the setting, which obviously would lead to a signal
// that we do not wwant right now
2024-01-27 20:16:14 +01:00
void RadioInterface : : new_channelIndex ( int index ) {
if ( channelSelector - > currentIndex ( ) = = index )
return ;
2024-03-04 14:45:33 +01:00
channelSelector - > setEnabled ( false ) ;
channelSelector - > setCurrentIndex ( index ) ;
channelSelector - > setEnabled ( true ) ;
2024-01-27 20:16:14 +01:00
}
//
/////////////////////////////////////////////////////////////////////////
// merely as a gadget, for each button the color can be set
// Lots of code, about 400 lines, just for a gadget
//
void RadioInterface : : set_Colors ( ) {
2024-02-25 14:18:27 +01:00
dabSettings_p - > beginGroup ( COLOR_SETTINGS ) ;
2024-01-27 20:16:14 +01:00
QString scanButton_color =
dabSettings_p - > value ( SCAN_BUTTON + " _color " ,
" white " ) . toString ( ) ;
QString scanButton_font =
dabSettings_p - > value ( SCAN_BUTTON + " _font " ,
" black " ) . toString ( ) ;
QString spectrumButton_color =
dabSettings_p - > value ( SPECTRUM_BUTTON + " _color " ,
" white " ) . toString ( ) ;
QString spectrumButton_font =
dabSettings_p - > value ( SPECTRUM_BUTTON + " _font " ,
" black " ) . toString ( ) ;
QString scanListButton_color =
dabSettings_p - > value ( SCANLIST_BUTTON + " _color " ,
" white " ) . toString ( ) ;
QString scanListButton_font =
dabSettings_p - > value ( SCANLIST_BUTTON + " _font " ,
" black " ) . toString ( ) ;
QString presetButton_color =
dabSettings_p - > value ( PRESET_BUTTON + " _color " ,
" white " ) . toString ( ) ;
QString presetButton_font =
dabSettings_p - > value ( PRESET_BUTTON + " _font " ,
" black " ) . toString ( ) ;
QString prevServiceButton_color =
dabSettings_p - > value ( PREVSERVICE_BUTTON + " _color " ,
" blaCK " ) . toString ( ) ;
QString prevServiceButton_font =
dabSettings_p - > value ( PREVSERVICE_BUTTON + " _font " ,
" white " ) . toString ( ) ;
QString nextServiceButton_color =
dabSettings_p - > value ( NEXTSERVICE_BUTTON + " _color " ,
" black " ) . toString ( ) ;
QString nextServiceButton_font =
dabSettings_p - > value ( NEXTSERVICE_BUTTON + " _font " ,
" white " ) . toString ( ) ;
QString configButton_color =
dabSettings_p - > value ( CONFIG_BUTTON + " _color " ,
" black " ) . toString ( ) ;
QString configButton_font =
dabSettings_p - > value ( CONFIG_BUTTON + " _font " ,
" white " ) . toString ( ) ;
QString httpButton_color =
dabSettings_p - > value ( HTTP_BUTTON + " _color " ,
" black " ) . toString ( ) ;
QString httpButton_font =
dabSettings_p - > value ( HTTP_BUTTON + " _font " ,
" white " ) . toString ( ) ;
dabSettings_p - > endGroup ( ) ;
QString temp = " QPushButton {background-color: %1; color: %2} " ;
spectrumButton - >
setStyleSheet ( temp . arg ( spectrumButton_color ,
spectrumButton_font ) ) ;
scanListButton - >
setStyleSheet ( temp . arg ( scanListButton_color ,
scanListButton_font ) ) ;
presetButton - >
setStyleSheet ( temp . arg ( presetButton_color ,
presetButton_font ) ) ;
scanButton - >
setStyleSheet ( temp . arg ( scanButton_color ,
scanButton_font ) ) ;
configButton - >
setStyleSheet ( temp . arg ( configButton_color ,
configButton_font ) ) ;
httpButton - >
setStyleSheet ( temp . arg ( httpButton_color ,
httpButton_font ) ) ;
prevServiceButton - >
setStyleSheet ( temp . arg ( prevServiceButton_color ,
prevServiceButton_font ) ) ;
nextServiceButton - >
setStyleSheet ( temp . arg ( nextServiceButton_color ,
nextServiceButton_font ) ) ;
}
void RadioInterface : : color_scanButton ( ) {
set_buttonColors ( scanButton , SCAN_BUTTON ) ;
}
void RadioInterface : : color_spectrumButton ( ) {
set_buttonColors ( spectrumButton , SPECTRUM_BUTTON ) ;
}
void RadioInterface : : color_scanListButton ( ) {
set_buttonColors ( scanListButton , SCANLIST_BUTTON ) ;
}
void RadioInterface : : color_presetButton ( ) {
set_buttonColors ( presetButton , PRESET_BUTTON ) ;
}
void RadioInterface : : color_prevServiceButton ( ) {
set_buttonColors ( prevServiceButton , PREVSERVICE_BUTTON ) ;
}
void RadioInterface : : color_nextServiceButton ( ) {
set_buttonColors ( nextServiceButton , NEXTSERVICE_BUTTON ) ;
}
void RadioInterface : : color_configButton ( ) {
set_buttonColors ( configButton , CONFIG_BUTTON ) ;
}
void RadioInterface : : color_httpButton ( ) {
set_buttonColors ( httpButton , HTTP_BUTTON ) ;
}
void RadioInterface : : set_buttonColors ( QPushButton * b ,
const QString & buttonName ) {
2024-04-22 20:35:15 +02:00
QColor baseColor , textColor ;
2024-02-06 15:37:07 +01:00
2024-04-22 20:35:15 +02:00
QColor color = QColorDialog : : getColor ( baseColor , nullptr , " baseColor " ) ;
2024-02-06 15:37:07 +01:00
if ( ! color . isValid ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-02-06 15:37:07 +01:00
baseColor = color ;
color = QColorDialog : : getColor ( textColor , nullptr , " textColor " ) ;
if ( ! color . isValid ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-02-06 15:37:07 +01:00
textColor = color ;
2024-01-27 20:16:14 +01:00
QString temp = " QPushButton {background-color: %1; color: %2} " ;
2024-02-06 15:37:07 +01:00
b - > setStyleSheet ( temp . arg ( baseColor . name ( ) ,
textColor . name ( ) ) ) ;
2024-01-27 20:16:14 +01:00
QString buttonColor = buttonName + " _color " ;
QString buttonFont = buttonName + " _font " ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > beginGroup ( COLOR_SETTINGS ) ;
2024-02-06 15:37:07 +01:00
dabSettings_p - > setValue ( buttonColor , baseColor . name ( ) ) ;
dabSettings_p - > setValue ( buttonFont , textColor . name ( ) ) ;
2024-01-27 20:16:14 +01:00
dabSettings_p - > endGroup ( ) ;
}
///////////////////////////////////////////////////////////////////////////
// Handling schedule
2024-04-19 18:34:50 +02:00
static
2024-06-01 11:12:04 +02:00
const char * scheduleList [ ] = { " nothing " , " exit " ,
" framedump " , " dltext " , " ficDump " } ;
2024-04-19 18:34:50 +02:00
2024-01-27 20:16:14 +01:00
void RadioInterface : : handle_scheduleButton ( ) {
QStringList candidates ;
scheduleSelector theSelector ;
QString scheduleService ;
2024-04-19 18:34:50 +02:00
for ( int i = 0 ; i < 5 ; i + + ) {
theSelector . addtoList ( QString ( scheduleList [ i ] ) ) ;
candidates + = QString ( scheduleList [ i ] ) ;
}
2024-01-27 20:16:14 +01:00
QStringList selectables = the_ensembleHandler - > getSelectables ( ) ;
for ( auto & candidate : selectables ) {
if ( ! candidates . contains ( candidate ) ) {
theSelector .
addtoList ( candidate ) ;
candidates + = candidate ;
}
}
int selected = theSelector . QDialog : : exec ( ) ;
scheduleService = candidates . at ( selected ) ;
{ elementSelector theElementSelector ( scheduleService ) ;
int targetTime = theElementSelector . QDialog : : exec ( ) ;
int delayDays = ( targetTime & 0XF0000 ) > > 16 ;
targetTime = targetTime & 0xFFFF ;
theScheduler . addRow ( scheduleService ,
delayDays ,
targetTime / 60 ,
targetTime % 60 ) ;
}
theScheduler . show ( ) ;
}
void RadioInterface : : scheduler_timeOut ( const QString & s ) {
if ( ! running . load ( ) )
return ;
if ( s = = " nothing " )
return ;
if ( s = = " exit " ) {
2024-02-16 15:46:54 +01:00
configHandler_p - > set_closeDirect ( true ) ;
2024-01-27 20:16:14 +01:00
QWidget : : close ( ) ;
return ;
}
if ( s = = " framedump " ) {
scheduled_frameDumping ( channel . currentService . serviceName ) ;
return ;
}
if ( s = = " audiodump " ) {
scheduled_audioDumping ( ) ;
return ;
}
if ( s = = " dlText " ) {
scheduled_dlTextDumping ( ) ;
return ;
}
if ( s = = " ficDump " ) {
scheduled_ficDumping ( ) ;
return ;
}
presetTimer . stop ( ) ;
stopScanning ( ) ;
scheduleSelect ( s ) ;
}
void RadioInterface : : scheduled_ficDumping ( ) {
if ( ficDumpPointer = = nullptr ) {
ficDumpPointer =
2024-06-01 11:12:04 +02:00
theFilenameFinder . find_ficDump_file ( channel . channelName ) ;
2024-01-27 20:16:14 +01:00
if ( ficDumpPointer = = nullptr )
return ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > start_ficDump ( ficDumpPointer ) ;
2024-01-27 20:16:14 +01:00
return ;
}
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_ficDump ( ) ;
2024-01-27 20:16:14 +01:00
ficDumpPointer = nullptr ;
}
//------------------------------------------------------------------------
//
// if configured, the interpreation of the EPG data starts automatically,
// the servicenames of an SPI/EPG service may differ from one country
// to another
void RadioInterface : : epgTimer_timeOut ( ) {
epgTimer . stop ( ) ;
2024-02-25 14:18:27 +01:00
if ( int_configValue ( " epgFlag " , 0 ) ! = 1 )
2024-01-27 20:16:14 +01:00
return ;
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
return ;
QStringList epgList = the_ensembleHandler - > get_epgServices ( ) ;
for ( auto serv : epgList ) {
packetdata pd ;
2024-07-16 19:52:55 +02:00
theOFDMHandler - > data_for_packetservice ( serv , pd , 0 ) ;
2024-01-27 20:16:14 +01:00
if ( ( ! pd . defined ) | |
( pd . DSCTy = = 0 ) | | ( pd . bitRate = = 0 ) )
continue ;
if ( pd . DSCTy = = 60 ) {
2024-10-14 13:12:03 +02:00
// LOG hidden service starts
2024-01-27 20:16:14 +01:00
fprintf ( stderr , " Starting hidden service %s \n " ,
serv . toUtf8 ( ) . data ( ) ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > set_dataChannel ( pd , & theDataBuffer , BACK_GROUND ) ;
2024-01-27 20:16:14 +01:00
dabService s ;
s . channel = pd . channel ;
s . serviceName = pd . serviceName ;
s . SId = pd . SId ;
2024-03-25 14:35:22 +01:00
s . SCIds = pd . SCIds ;
2024-01-27 20:16:14 +01:00
s . subChId = pd . subchId ;
s . fd = nullptr ;
channel . backgroundServices . push_back ( s ) ;
}
}
}
void RadioInterface : : set_epgData ( int SId , int theTime ,
const QString & theText ,
const QString & theDescr ) {
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler ! = nullptr )
theOFDMHandler - > set_epgData ( SId , theTime ,
2024-01-27 20:16:14 +01:00
theText , theDescr ) ;
}
void RadioInterface : : handle_timeTable ( ) {
int epgWidth ;
if ( ! my_timeTable - > isHidden ( ) ) {
my_timeTable - > hide ( ) ;
return ;
}
if ( ! channel . currentService . valid | |
! channel . currentService . is_audio )
return ;
my_timeTable - > clear ( ) ;
epgWidth = dabSettings_p - > value ( " epgWidth " , 70 ) . toInt ( ) ;
if ( epgWidth < 50 )
epgWidth = 50 ;
std : : vector < epgElement > res =
2024-06-01 11:12:04 +02:00
theOFDMHandler - > find_epgData ( channel . currentService . SId ) ;
2024-01-27 20:16:14 +01:00
for ( const auto & element : res )
my_timeTable - > addElement ( element . theTime ,
epgWidth ,
element . theText ,
element . theDescr ) ;
my_timeTable - > show ( ) ;
}
//----------------------------------------------------------------------
//
void RadioInterface : : scheduled_dlTextDumping ( ) {
if ( dlTextFile ! = nullptr ) {
fclose ( dlTextFile ) ;
dlTextFile = nullptr ;
2024-02-16 15:46:54 +01:00
configHandler_p - > mark_dlTextButton ( false ) ;
2024-01-27 20:16:14 +01:00
return ;
}
2024-06-01 11:12:04 +02:00
QString fileName = theFilenameFinder . finddlText_fileName ( false ) ;
2024-01-27 20:16:14 +01:00
dlTextFile = fopen ( fileName . toUtf8 ( ) . data ( ) , " w+ " ) ;
if ( dlTextFile = = nullptr )
return ;
2024-02-16 15:46:54 +01:00
configHandler_p - > mark_dlTextButton ( true ) ;
2024-01-27 20:16:14 +01:00
}
//
//---------------------------------------------------------------------
//
void RadioInterface : : handle_configButton ( ) {
2024-02-16 15:46:54 +01:00
if ( ! configHandler_p - > isHidden ( ) ) {
configHandler_p - > hide ( ) ;
2024-03-13 19:45:53 +01:00
dabSettings_p - > setValue ( CONFIG_WIDGET_VISIBLE , 0 ) ;
2024-01-27 20:16:14 +01:00
}
else {
2024-02-16 15:46:54 +01:00
configHandler_p - > show ( ) ;
2024-03-13 19:45:53 +01:00
dabSettings_p - > setValue ( CONFIG_WIDGET_VISIBLE , 1 ) ;
2024-01-27 20:16:14 +01:00
}
}
void RadioInterface : : handle_devicewidgetButton ( ) {
if ( inputDevice_p = = nullptr )
return ;
2024-03-24 14:07:49 +01:00
fprintf ( stderr , " setting visibility to %d \n " ,
! inputDevice_p - > getVisibility ( ) ) ;
2024-01-27 20:16:14 +01:00
inputDevice_p - > setVisibility ( ! inputDevice_p - > getVisibility ( ) ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( DEVICE_WIDGET_VISIBLE ,
2024-01-27 20:16:14 +01:00
inputDevice_p - > getVisibility ( ) ? 1 : 0 ) ;
}
2024-02-16 15:46:54 +01:00
//
// called from the configHandler
2024-01-27 20:16:14 +01:00
void RadioInterface : : handle_dlTextButton ( ) {
if ( dlTextFile ! = nullptr ) {
fclose ( dlTextFile ) ;
dlTextFile = nullptr ;
2024-02-16 15:46:54 +01:00
configHandler_p - > mark_dlTextButton ( false ) ;
2024-01-27 20:16:14 +01:00
return ;
}
2024-06-01 11:12:04 +02:00
QString fileName = theFilenameFinder . finddlText_fileName ( true ) ;
2024-01-27 20:16:14 +01:00
dlTextFile = fopen ( fileName . toUtf8 ( ) . data ( ) , " w+ " ) ;
if ( dlTextFile = = nullptr )
return ;
2024-02-16 15:46:54 +01:00
configHandler_p - > mark_dlTextButton ( true ) ;
2024-01-27 20:16:14 +01:00
}
2024-02-16 15:46:54 +01:00
//
// called from the config handler
2024-01-27 20:16:14 +01:00
void RadioInterface : : handle_resetButton ( ) {
if ( ! running . load ( ) )
return ;
QString channelName = channel . channelName ;
stopScanning ( ) ;
stopChannel ( ) ;
startChannel ( channelName ) ;
}
2024-02-16 15:46:54 +01:00
//
// called from the config handler
2024-01-27 20:16:14 +01:00
void RadioInterface : : handle_snrButton ( ) {
if ( ! running . load ( ) )
return ;
2024-06-01 11:12:04 +02:00
if ( theSNRViewer . isHidden ( ) )
theSNRViewer . show ( ) ;
2024-01-27 20:16:14 +01:00
else
2024-06-01 11:12:04 +02:00
theSNRViewer . hide ( ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( SNR_WIDGET_VISIBLE ,
2024-06-01 11:12:04 +02:00
theSNRViewer . isHidden ( ) ? 0 : 1 ) ;
2024-01-27 20:16:14 +01:00
}
2024-02-16 15:46:54 +01:00
//
// called from the configHandler
2024-01-27 20:16:14 +01:00
void RadioInterface : : handle_set_coordinatesButton ( ) {
coordinates theCoordinator ( dabSettings_p ) ;
( void ) theCoordinator . QDialog : : exec ( ) ;
2024-02-16 15:46:54 +01:00
localPos . latitude =
2024-02-25 14:18:27 +01:00
dabSettings_p - > value ( HOME_LATITUDE , 0 ) . toFloat ( ) ;
2024-02-16 15:46:54 +01:00
localPos . longitude =
2024-02-25 14:18:27 +01:00
dabSettings_p - > value ( HOME_LONGITUDE , 0 ) . toFloat ( ) ;
2024-01-27 20:16:14 +01:00
}
2024-02-16 15:46:54 +01:00
//
// called from the configHandler
2024-01-27 20:16:14 +01:00
void RadioInterface : : handle_loadTable ( ) {
2024-02-25 14:18:27 +01:00
dbLoader theLoader ( dabSettings_p ) ;
if ( theLoader . load_db ( ) ) {
2024-01-27 20:16:14 +01:00
QMessageBox : : information ( this , tr ( " success " ) ,
tr ( " Loading and installing database complete \n " ) ) ;
2024-06-01 11:12:04 +02:00
theTIIProcessor . reload ( ) ;
2024-01-27 20:16:14 +01:00
}
else {
QMessageBox : : information ( this , tr ( " fail " ) ,
tr ( " Loading database failed \n " ) ) ;
}
}
void RadioInterface : : stop_sourcedumping ( ) {
2024-07-29 20:19:31 +02:00
if ( ! sourceDumping )
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_SOURCEDUMP_STOPS ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_dumping ( ) ;
2024-07-27 15:30:56 +02:00
sourceDumping = false ;
2024-02-16 15:46:54 +01:00
configHandler_p - > mark_dumpButton ( false ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : start_sourcedumping ( ) {
QString deviceName = inputDevice_p - > deviceName ( ) ;
QString channelName = channel . channelName ;
2024-06-01 11:12:04 +02:00
if ( theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-07-27 15:30:56 +02:00
QString rawDumpName =
2024-06-01 11:12:04 +02:00
theFilenameFinder . findRawDump_fileName ( deviceName , channelName ) ;
2024-07-27 15:30:56 +02:00
if ( rawDumpName = = " " )
2024-01-27 20:16:14 +01:00
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_SOURCEDUMP_STARTS ,
deviceName , channelName ) ;
2024-02-16 15:46:54 +01:00
configHandler_p - > mark_dumpButton ( true ) ;
2024-07-27 15:30:56 +02:00
theOFDMHandler - > start_dumping ( rawDumpName , channel . tunedFrequency ) ;
sourceDumping = true ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : handle_sourcedumpButton ( ) {
2024-06-01 11:12:04 +02:00
if ( ! running . load ( ) | | theSCANHandler . active ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-07-27 15:30:56 +02:00
if ( sourceDumping )
2024-01-27 20:16:14 +01:00
stop_sourcedumping ( ) ;
else
start_sourcedumping ( ) ;
}
void RadioInterface : : handle_LoggerButton ( int s ) {
( void ) s ;
2024-02-16 15:46:54 +01:00
if ( configHandler_p - > logger_active ( ) ) {
2024-10-14 13:12:03 +02:00
theLogger . logging_starts ( ) ;
dabSettings_p - > setValue ( " logMode " , 1 ) ;
2024-01-27 20:16:14 +01:00
}
2024-10-14 13:12:03 +02:00
else {
theLogger . logging_stops ( ) ;
dabSettings_p - > setValue ( " logMode " , 0 ) ;
2024-01-27 20:16:14 +01:00
}
}
2024-02-16 15:46:54 +01:00
void RadioInterface : : set_tii_detectorMode ( bool isChecked ) {
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler ! = nullptr )
theOFDMHandler - > set_tiiDetectorMode ( isChecked ) ;
2024-01-27 20:16:14 +01:00
}
2024-02-25 14:18:27 +01:00
void RadioInterface : : handle_dcRemovalSelector ( bool b ) {
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler ! = nullptr )
theOFDMHandler - > set_dcRemoval ( b ) ;
theNewDisplay . set_dcRemoval ( b ) ;
2024-01-27 20:16:14 +01:00
}
2024-02-16 15:46:54 +01:00
void RadioInterface : : set_transmitters_local ( bool isChecked ) {
2024-01-27 20:16:14 +01:00
maxDistance = - 1 ;
channel . targetPos = position { 0 , 0 } ;
2024-02-16 15:46:54 +01:00
if ( ( isChecked ) & & ( mapHandler ! = nullptr ) )
2024-02-25 14:18:27 +01:00
mapHandler - > putData ( MAP_RESET , channel . targetPos ) ;
2024-01-27 20:16:14 +01:00
}
2024-02-16 15:46:54 +01:00
void RadioInterface : : selectDecoder ( int decoder ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > handle_decoderSelector ( decoder ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : set_streamSelector ( int k ) {
if ( ! running . load ( ) )
return ;
( ( audioSink * ) ( soundOut_p ) ) - > selectDevice ( k ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( AUDIO_STREAM_NAME ,
2024-02-16 15:46:54 +01:00
configHandler_p - > currentStream ( ) ) ;
2024-01-27 20:16:14 +01:00
}
//
//////////////////////////////////////////////////////////////////////////
void RadioInterface : : nrServices ( int n ) {
channel . serviceCount = n ;
}
2024-04-19 18:34:50 +02:00
bool RadioInterface : : autoStart_http ( ) {
if ( localPos . latitude = = 0 )
return false ;
if ( mapHandler ! = nullptr )
return false ;
QString browserAddress =
dabSettings_p - > value ( BROWSER_ADDRESS ,
" http://localhost " ) . toString ( ) ;
QString mapPort =
dabSettings_p - > value ( MAP_PORT_SETTING ,
8080 ) . toString ( ) ;
mapHandler = new httpHandler ( this ,
mapPort ,
browserAddress ,
localPos ,
" " ,
configHandler_p - > localBrowserSelector_active ( ) , dabSettings_p ) ;
maxDistance = - 1 ;
return mapHandler ! = nullptr ;
}
2024-01-27 20:16:14 +01:00
// ensure that we only get a handler if we have a start location
void RadioInterface : : handle_httpButton ( ) {
2024-02-16 15:46:54 +01:00
if ( localPos . latitude = = 0 ) {
2024-01-27 20:16:14 +01:00
QMessageBox : : information ( this , tr ( " Warning " ) ,
tr ( " Function not available, no coordinates were found " ) ) ;
return ;
}
if ( mapHandler = = nullptr ) {
QString browserAddress =
2024-02-25 14:18:27 +01:00
dabSettings_p - > value ( BROWSER_ADDRESS ,
2024-02-16 15:46:54 +01:00
" http://localhost " ) . toString ( ) ;
2024-01-27 20:16:14 +01:00
QString mapPort =
2024-02-25 14:18:27 +01:00
dabSettings_p - > value ( MAP_PORT_SETTING ,
8080 ) . toString ( ) ;
2024-01-27 20:16:14 +01:00
QString mapFile ;
2024-02-25 14:18:27 +01:00
if ( configHandler_p - > transmitterNames_active ( ) )
2024-06-01 11:12:04 +02:00
mapFile = theFilenameFinder . findMaps_fileName ( ) ;
2024-02-25 14:18:27 +01:00
else
mapFile = " " ;
2024-02-16 15:46:54 +01:00
2024-01-27 20:16:14 +01:00
mapHandler = new httpHandler ( this ,
mapPort ,
browserAddress ,
2024-02-16 15:46:54 +01:00
localPos ,
2024-01-27 20:16:14 +01:00
mapFile ,
2024-04-16 15:18:29 +02:00
configHandler_p - > localBrowserSelector_active ( ) , dabSettings_p ) ;
2024-01-27 20:16:14 +01:00
maxDistance = - 1 ;
if ( mapHandler ! = nullptr )
httpButton - > setText ( " http-on " ) ;
}
else {
locker . lock ( ) ;
delete mapHandler ;
mapHandler = nullptr ;
locker . unlock ( ) ;
httpButton - > setText ( " http " ) ;
}
}
void RadioInterface : : http_terminate ( ) {
locker . lock ( ) ;
if ( mapHandler ! = nullptr ) {
delete mapHandler ;
mapHandler = nullptr ;
}
locker . unlock ( ) ;
httpButton - > setText ( " http " ) ;
}
void RadioInterface : : displaySlide ( const QPixmap & p ) {
int w = 360 ;
int h = 2 * w / 3 ;
2024-03-13 19:45:53 +01:00
pauzeTimer . stop ( ) ;
2024-01-27 20:16:14 +01:00
pictureLabel - > setAlignment ( Qt : : AlignCenter ) ;
pictureLabel - >
setPixmap ( p . scaled ( w , h , Qt : : KeepAspectRatio ) ) ;
pictureLabel - > show ( ) ;
}
void RadioInterface : : show_pauzeSlide ( ) {
QPixmap p ;
2024-03-04 14:45:33 +01:00
QString slideName = " :res/pauze-slide-%1.png " ;
2024-03-13 19:45:53 +01:00
pauzeTimer . stop ( ) ;
2024-08-15 13:16:44 +02:00
int nr = rand ( ) % 11 ;
slideName = slideName . arg ( nr ) ;
2024-03-04 14:45:33 +01:00
if ( p . load ( slideName , " png " ) )
2024-01-27 20:16:14 +01:00
displaySlide ( p ) ;
2024-08-15 13:16:44 +02:00
pauzeTimer . start ( 1 * 30 * 1000 ) ;
2024-01-27 20:16:14 +01:00
}
//////////////////////////////////////////////////////////////////////////
// Experimental: handling eti
// writing an eti file and scanning seems incompatible to me, so
// that is why I use the button, originally named "scanButton"
// for eti when eti is prepared.
// Preparing eti is with a checkbox on the configuration widget
//
/////////////////////////////////////////////////////////////////////////
void RadioInterface : : handle_etiHandler ( ) {
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler = = nullptr ) // should not happen
2024-01-27 20:16:14 +01:00
return ;
if ( channel . etiActive )
stop_etiHandler ( ) ;
else
start_etiHandler ( ) ;
}
void RadioInterface : : stop_etiHandler ( ) {
if ( ! channel . etiActive )
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_ETI_STOPS ) ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_etiGenerator ( ) ;
2024-01-27 20:16:14 +01:00
channel . etiActive = false ;
scanButton - > setText ( " eti " ) ;
}
void RadioInterface : : start_etiHandler ( ) {
if ( channel . etiActive )
return ;
2024-06-01 11:12:04 +02:00
QString etiFile = theFilenameFinder .
2024-01-27 20:16:14 +01:00
find_eti_fileName ( channel . ensembleName , channel . channelName ) ;
if ( etiFile = = QString ( " " ) )
return ;
2024-10-14 13:12:03 +02:00
theLogger . log ( logger : : LOG_ETI_STARTS ,
inputDevice_p - > deviceName ( ) ,
channel . channelName ) ;
2024-06-01 11:12:04 +02:00
channel . etiActive = theOFDMHandler - > start_etiGenerator ( etiFile ) ;
2024-01-27 20:16:14 +01:00
if ( channel . etiActive )
scanButton - > setText ( " eti runs " ) ;
}
void RadioInterface : : handle_eti_activeSelector ( int k ) {
2024-02-16 15:46:54 +01:00
bool setting = configHandler_p - > eti_active ( ) ;
2024-01-27 20:16:14 +01:00
( void ) k ;
if ( inputDevice_p = = nullptr )
return ;
if ( setting ) {
stopScanning ( ) ;
2024-04-14 12:47:14 +02:00
disconnect ( scanButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_scanButton ) ;
connect ( scanButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_etiHandler ) ;
2024-01-27 20:16:14 +01:00
scanButton - > setText ( " eti " ) ;
if ( ! inputDevice_p - > isFileInput ( ) ) // restore the button' visibility
scanButton - > show ( ) ;
return ;
}
// otherwise, disconnect the eti handling and reconnect scan
// be careful, an ETI session may be going on
stop_etiHandler ( ) ; // just in case
2024-04-14 12:47:14 +02:00
disconnect ( scanButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_etiHandler ) ;
connect ( scanButton , & QPushButton : : clicked ,
this , & RadioInterface : : handle_scanButton ) ;
2024-01-27 20:16:14 +01:00
scanButton - > setText ( " scan " ) ;
if ( inputDevice_p - > isFileInput ( ) ) // hide the button now
scanButton - > hide ( ) ;
}
//
// access functions to the display widget
void RadioInterface : : show_spectrum ( int amount ) {
std : : vector < Complex > inBuffer ( 2048 ) ;
( void ) amount ;
2024-06-01 11:12:04 +02:00
if ( theSpectrumBuffer . GetRingBufferReadAvailable ( ) < 2048 )
2024-01-27 20:16:14 +01:00
return ;
2024-06-01 11:12:04 +02:00
theSpectrumBuffer . getDataFromBuffer ( inBuffer . data ( ) , 2048 ) ;
theSpectrumBuffer . FlushRingBuffer ( ) ;
if ( ! theNewDisplay . isHidden ( ) & &
( theNewDisplay . get_tab ( ) = = SHOW_SPECTRUM ) )
theNewDisplay . show_spectrum ( inBuffer , channel . tunedFrequency ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : show_tii_spectrum ( ) {
std : : vector < Complex > inBuffer ( 2048 ) ;
2024-06-01 11:12:04 +02:00
if ( theTIIBuffer . GetRingBufferReadAvailable ( ) < 2048 )
2024-01-27 20:16:14 +01:00
return ;
2024-06-01 11:12:04 +02:00
theTIIBuffer . getDataFromBuffer ( inBuffer . data ( ) , 2048 ) ;
theTIIBuffer . FlushRingBuffer ( ) ;
if ( ! theNewDisplay . isHidden ( ) & &
( theNewDisplay . get_tab ( ) = = SHOW_TII ) )
theNewDisplay . show_tii ( inBuffer , channel . tunedFrequency ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : show_correlation ( int s , int g , QVector < int > r ) {
2024-03-13 19:45:53 +01:00
std : : vector < float > inBuffer ( s ) ;
2024-01-27 20:16:14 +01:00
( void ) g ;
2024-06-01 11:12:04 +02:00
theResponseBuffer . getDataFromBuffer ( inBuffer . data ( ) , s ) ;
theResponseBuffer . FlushRingBuffer ( ) ;
if ( ! theNewDisplay . isHidden ( ) ) {
if ( theNewDisplay . get_tab ( ) = = SHOW_CORRELATION )
theNewDisplay . show_correlation ( inBuffer , g , r , channel . distance ) ;
2024-01-27 20:16:14 +01:00
}
}
2024-04-03 18:44:52 +02:00
2024-01-27 20:16:14 +01:00
void RadioInterface : : show_null ( int amount ) {
2024-03-13 19:45:53 +01:00
Complex * inBuffer = ( Complex * ) ( alloca ( amount * sizeof ( Complex ) ) ) ;
2024-06-01 11:12:04 +02:00
theNULLBuffer . getDataFromBuffer ( inBuffer , amount ) ;
if ( ! theNewDisplay . isHidden ( ) )
if ( theNewDisplay . get_tab ( ) = = SHOW_NULL )
theNewDisplay . show_null ( inBuffer , amount ) ;
2024-01-27 20:16:14 +01:00
}
2024-04-03 18:44:52 +02:00
void RadioInterface : : show_tii ( int tiiValue , int index ) {
2024-01-27 20:16:14 +01:00
QString country = " " ;
2024-04-03 18:44:52 +02:00
int mainId = tiiValue > > 8 ;
cacheElement theTransmitter ;
2024-04-10 19:49:55 +02:00
bool listChanged = false ;
2024-01-27 20:16:14 +01:00
2024-04-03 18:44:52 +02:00
bool dxMode = configHandler_p - > get_dxSelector ( ) ;
2024-10-09 17:57:23 +02:00
if ( ! dxMode ) {
2024-04-03 18:44:52 +02:00
channel . transmitters . resize ( 0 ) ;
2024-10-09 17:57:23 +02:00
if ( ! theNewDisplay . isHidden ( ) )
theNewDisplay . hide ( ) ;
}
2024-09-23 10:19:31 +02:00
2024-01-27 20:16:14 +01:00
if ( ! running . load ( ) | | ( mainId = = 0xFF ) ) // shouldn't be
return ;
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler - > get_ecc ( ) = = 0 )
2024-04-03 18:44:52 +02:00
return ;
2024-01-27 20:16:14 +01:00
2024-04-03 18:44:52 +02:00
if ( ! channel . has_ecc ) {
2024-06-01 11:12:04 +02:00
channel . ecc_byte = theOFDMHandler - > get_ecc ( ) ;
2024-01-27 20:16:14 +01:00
country = find_ITU_code ( channel . ecc_byte ,
( channel . Eid > > 12 ) & 0xF ) ;
channel . has_ecc = true ;
2024-08-27 12:40:14 +02:00
channel . countryName = country ;
2024-01-27 20:16:14 +01:00
channel . transmitterName = " " ;
transmitter_country - > setText ( country ) ;
}
2024-07-27 15:30:56 +02:00
2024-02-25 14:18:27 +01:00
if ( ( localPos . latitude = = 0 ) | | ( localPos . longitude = = 0 ) )
return ;
2024-06-01 11:12:04 +02:00
if ( ! theTIIProcessor . has_tiiFile ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-04-19 18:34:50 +02:00
2024-04-10 19:49:55 +02:00
// OK, here we really start
2024-09-23 10:19:31 +02:00
// first we check whether the item is already in the list, however
// if it is but was not found in the database and now it is,
// replace the item
bool inList = false ;
cacheElement * tr =
2024-06-01 11:12:04 +02:00
theTIIProcessor . get_transmitter ( channel . realChannel ?
2024-02-25 14:18:27 +01:00
channel . channelName :
" any " ,
channel . Eid ,
2024-04-03 18:44:52 +02:00
tiiValue > > 8 , tiiValue & 0xFF ) ;
2024-09-23 10:19:31 +02:00
for ( uint16_t i = 0 ; i < channel . transmitters . size ( ) ; i + + ) {
cacheElement t2 =
channel . transmitters . at ( i ) . theTransmitter ;
if ( ( channel . transmitters . at ( i ) . tiiValue = = tiiValue ) ) {
if ( ! t2 . valid & & tr - > valid ) {
channel . transmitters . erase ( channel . transmitters . begin ( ) + i ) ;
i - = 1 ;
// fprintf (stderr, "removing an element\n");
}
else {
inList = true ;
break ;
}
2024-09-18 12:08:40 +02:00
}
2024-09-23 10:19:31 +02:00
}
2024-10-09 17:57:23 +02:00
2024-09-23 10:19:31 +02:00
//
// If the item is not yet in the list add it and - in dxMode
// add the data to the log
if ( ! inList ) {
2024-04-10 19:49:55 +02:00
theTransmitter = * tr ;
2024-09-23 10:19:31 +02:00
theTransmitter . mainId = tiiValue > > 8 ;
theTransmitter . subId = tiiValue & 0xFF ;
theTransmitter . channel = channel . channelName ;
2024-04-10 19:49:55 +02:00
transmitterDesc t = { tiiValue , false , theTransmitter , 0 , 0 } ;
channel . transmitters . push_back ( t ) ;
2024-09-23 10:19:31 +02:00
if ( dxMode ) {
2024-10-09 17:57:23 +02:00
if ( theNewDisplay . isHidden ( ) & &
dabSettings_p - > value ( NEW_DISPLAY_VISIBLE , 0 ) . toInt ( ) ! = 0 )
theNewDisplay . show ( ) ;
2024-09-23 10:19:31 +02:00
FILE * tiiFile =
2024-10-09 17:57:23 +02:00
fopen ( QString ( path_for_tiiFile + " tii-files.txt " ) .
2024-09-23 10:19:31 +02:00
toStdString ( ) . c_str ( ) , " a " ) ;
if ( tiiFile ! = nullptr ) {
QDateTime theTime ;
QString tod = theTime . currentDateTime ( ) . toString ( ) ;
fprintf ( tiiFile , " %s -> %s %s %d %d %s \n " ,
tod . toLatin1 ( ) . data ( ) ,
channel . countryName . toLatin1 ( ) . data ( ) ,
channel . channelName . toLatin1 ( ) . data ( ) ,
tiiValue > > 8 , tiiValue & 0xFF ,
theTransmitter . transmitterName . toLatin1 ( ) . data ( ) ) ;
fclose ( tiiFile ) ;
}
}
2024-04-10 19:49:55 +02:00
listChanged = true ;
2024-01-27 20:16:14 +01:00
}
2024-04-10 19:49:55 +02:00
//
// Check which one is "strongest",
2024-04-03 18:44:52 +02:00
if ( index = = 0 ) {
2024-04-10 19:49:55 +02:00
int currentMax = - 1 ;
for ( uint16_t i = 0 ; i < channel . transmitters . size ( ) ; i + + ) {
if ( channel . transmitters . at ( i ) . isStrongest )
currentMax = i ;
2024-04-03 18:44:52 +02:00
channel . transmitters . at ( i ) . isStrongest = false ;
2024-04-10 19:49:55 +02:00
}
for ( uint16_t i = 0 ; i < channel . transmitters . size ( ) ; i + + ) {
if ( channel . transmitters . at ( i ) . tiiValue = = tiiValue ) {
channel . transmitters . at ( i ) . isStrongest = true ;
if ( i ! = currentMax )
listChanged = true ;
}
}
2024-04-03 18:44:52 +02:00
}
// display the transmitters on the scope widget
2024-06-01 11:12:04 +02:00
if ( ! ( theNewDisplay . isHidden ( ) & &
( theNewDisplay . get_tab ( ) = = SHOW_TII ) ) )
theNewDisplay . show_transmitters ( channel . transmitters ) ;
2024-04-03 18:44:52 +02:00
//
// and recompute distances etc etc
if ( ! dxMode ) {
QFont f ( " Arial " , 9 ) ;
distanceLabel - > setFont ( f ) ;
}
else {
2024-04-15 14:03:12 +02:00
if ( listChanged ) // adapt the list and display
2024-06-01 11:12:04 +02:00
theDXDisplay . cleanUp ( ) ;
theDXDisplay . show ( ) ;
theDXDisplay . setChannel ( channel . channelName ) ;
2024-04-03 18:44:52 +02:00
}
2024-04-10 19:49:55 +02:00
if ( ! listChanged & & dxMode )
return ;
//
// The list was changed, so we rewrite the dxDisplay and
// the map
2024-04-03 18:44:52 +02:00
QString labelText ;
for ( auto & theTr : channel . transmitters ) {
position thePosition ;
thePosition . latitude = theTr . theTransmitter . latitude ;
thePosition . longitude = theTr . theTransmitter . longitude ;
2024-09-23 10:19:31 +02:00
if ( theTr . theTransmitter . valid & & theTr . isStrongest ) {
2024-04-03 18:44:52 +02:00
channel . targetPos . latitude = thePosition . latitude ;
channel . targetPos . longitude = thePosition . longitude ;
channel . transmitterName =
theTr . theTransmitter . transmitterName ;
channel . mainId = theTr . tiiValue > > 8 ;
channel . subId = theTr . tiiValue & 0xFF ;
}
QString theName = theTr . theTransmitter . transmitterName ;
float power = theTr . theTransmitter . power ;
float height = theTr . theTransmitter . height ;
2024-01-27 20:16:14 +01:00
// if positions are known, we can compute distance and corner
2024-04-10 19:49:55 +02:00
theTr . distance = distance ( thePosition , localPos ) ;
theTr . corner = corner ( thePosition , localPos ) ;
2024-04-03 18:44:52 +02:00
if ( theTr . isStrongest ) {
2024-04-10 19:49:55 +02:00
channel . distance = theTr . distance ;
channel . corner = theTr . corner ;
2024-04-03 18:44:52 +02:00
channel . height = height ;
}
2024-04-04 15:13:56 +02:00
int tiiValue_local = theTr . tiiValue ;
labelText = " ( " + QString : : number ( tiiValue_local > > 8 ) + " , "
2024-09-23 10:19:31 +02:00
+ QString : : number ( tiiValue_local & 0xFF ) + " ) " ;
if ( theTr . theTransmitter . valid )
labelText + = theName ;
else
labelText + = " Not in database " ;
QString text2 = " " ;
if ( theTr . theTransmitter . valid )
text2 = " "
2024-04-10 19:49:55 +02:00
+ QString : : number ( theTr . distance , ' f ' , 1 ) + " km "
+ QString : : number ( theTr . corner , ' f ' , 1 )
2024-04-03 18:44:52 +02:00
+ QString : : fromLatin1 ( " \xb0 " )
2024-04-15 14:03:12 +02:00
+ " ( " + QString : : number ( height , ' f ' , 1 ) + " m) "
+ " " + QString : : number ( power , ' f ' , 1 ) + " kW " ;
2024-04-04 15:13:56 +02:00
if ( dxMode )
2024-06-01 11:12:04 +02:00
theDXDisplay . addRow ( labelText , text2 , theTr . isStrongest ) ;
2024-04-04 15:13:56 +02:00
else
distanceLabel - > setText ( labelText + text2 ) ;
2024-04-03 18:44:52 +02:00
2024-01-27 20:16:14 +01:00
// see if we have a map
2024-04-03 18:44:52 +02:00
if ( mapHandler = = nullptr )
continue ;
2024-01-27 20:16:14 +01:00
2024-04-03 18:44:52 +02:00
uint8_t key = MAP_NORM_TRANS ; // default value
bool localTransmitters =
2024-02-16 15:46:54 +01:00
configHandler_p - > localTransmitterSelector_active ( ) ;
2024-04-10 19:49:55 +02:00
if ( ( ! localTransmitters ) & & ( theTr . distance > maxDistance ) ) {
maxDistance = theTr . distance ;
2024-04-03 18:44:52 +02:00
key = MAP_MAX_TRANS ;
}
2024-01-27 20:16:14 +01:00
//
2024-04-03 18:44:52 +02:00
QDateTime theTime =
2024-02-16 15:46:54 +01:00
configHandler_p - > utcSelector_active ( ) ?
2024-04-03 18:44:52 +02:00
QDateTime : : currentDateTimeUtc ( ) :
QDateTime : : currentDateTime ( ) ;
2024-09-23 10:19:31 +02:00
if ( listChanged & & theTr . theTransmitter . valid )
2024-06-15 13:12:16 +02:00
mapHandler - > putData ( key ,
thePosition ,
theTr . theTransmitter . transmitterName ,
channel . channelName ,
theTime . toString ( Qt : : TextDate ) ,
theTr . tiiValue ,
channel . snr ,
theTr . distance ,
theTr . corner , power , height ) ;
2024-04-03 18:44:52 +02:00
}
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : showIQ ( int amount ) {
std : : vector < Complex > Values ( amount ) ;
2024-06-01 11:12:04 +02:00
theIQBuffer . getDataFromBuffer ( Values . data ( ) , amount ) ;
theIQBuffer . FlushRingBuffer ( ) ;
if ( ! theNewDisplay . isHidden ( ) )
theNewDisplay . showIQ ( Values ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : show_Corrector ( int h , float l ) {
2024-06-01 11:12:04 +02:00
if ( ! theNewDisplay . isHidden ( ) )
theNewDisplay . show_corrector ( h , l ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : show_stdDev ( int amount ) {
std : : vector < float > Values ( amount ) ;
stdDevBuffer . getDataFromBuffer ( Values . data ( ) , amount ) ;
2024-06-01 11:12:04 +02:00
if ( ! theNewDisplay . isHidden ( ) )
theNewDisplay . show_stdDev ( Values ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : show_snr ( float snr ) {
QPixmap p ;
2024-06-01 11:12:04 +02:00
if ( ! theNewDisplay . isHidden ( ) )
theNewDisplay . show_snr ( snr ) ;
2024-01-27 20:16:14 +01:00
channel . snr = snr ;
if ( snr < 5 )
p = strengthLabels . at ( 0 ) ;
else
if ( snr < 8 )
p = strengthLabels . at ( 1 ) ;
else
if ( snr < 12 )
p = strengthLabels . at ( 2 ) ;
else
p = strengthLabels . at ( 3 ) ;
this - > snrLabel - > setAlignment ( Qt : : AlignRight ) ;
this - > snrLabel - > setPixmap ( p . scaled ( 30 , 30 , Qt : : KeepAspectRatio ) ) ;
2024-06-01 11:12:04 +02:00
if ( theSNRViewer . isHidden ( ) ) {
theSNRBuffer . FlushRingBuffer ( ) ;
2024-01-27 20:16:14 +01:00
return ;
}
2024-06-01 11:12:04 +02:00
int amount = theSNRBuffer . GetRingBufferReadAvailable ( ) ;
2024-01-27 20:16:14 +01:00
if ( amount < = 0 )
return ;
2024-03-13 19:45:53 +01:00
float * ss = ( float * ) alloca ( amount * sizeof ( float ) ) ;
2024-06-01 11:12:04 +02:00
theSNRBuffer . getDataFromBuffer ( ss , amount ) ;
2024-01-27 20:16:14 +01:00
for ( int i = 0 ; i < amount ; i + + ) {
2024-06-01 11:12:04 +02:00
theSNRViewer . add_snr ( ss [ i ] ) ;
2024-01-27 20:16:14 +01:00
}
2024-06-01 11:12:04 +02:00
theSNRViewer . show_snr ( ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : show_quality ( float q ,
float sco , float freqOffset ) {
2024-06-01 11:12:04 +02:00
if ( ! running . load ( ) | | theNewDisplay . isHidden ( ) )
2024-01-27 20:16:14 +01:00
return ;
2024-06-01 11:12:04 +02:00
theNewDisplay . show_quality ( q , sco , freqOffset ) ;
2024-01-27 20:16:14 +01:00
}
//
// called from the MP4 decoder
void RadioInterface : : show_rsCorrections ( int c , int ec ) {
if ( ! running )
return ;
if ( ! techWindow_p - > isHidden ( ) )
techWindow_p - > show_rsCorrections ( c , ec ) ;
}
//
2024-04-19 18:34:50 +02:00
// called from the ofdm handler
2024-01-27 20:16:14 +01:00
void RadioInterface : : show_clock_error ( int d ) {
if ( ! running . load ( ) )
return ;
2024-06-01 11:12:04 +02:00
if ( ! theNewDisplay . isHidden ( ) ) {
theNewDisplay . show_clock_err ( d ) ;
2024-01-27 20:16:14 +01:00
}
}
void RadioInterface : : show_channel ( int n ) {
std : : vector < Complex > v ( n ) ;
2024-06-01 11:12:04 +02:00
theChannelBuffer . getDataFromBuffer ( v . data ( ) , n ) ;
theChannelBuffer . FlushRingBuffer ( ) ;
if ( ! theNewDisplay . isHidden ( ) & &
( theNewDisplay . get_tab ( ) = = SHOW_CHANNEL ) )
theNewDisplay . show_channel ( v ) ;
2024-01-27 20:16:14 +01:00
}
bool RadioInterface : : channelOn ( ) {
2024-06-01 11:12:04 +02:00
return ( ! theNewDisplay . isHidden ( ) & &
( theNewDisplay . get_tab ( ) = = SHOW_CHANNEL ) ) ;
2024-01-27 20:16:14 +01:00
}
bool RadioInterface : : devScopeOn ( ) {
2024-06-01 11:12:04 +02:00
return ! theNewDisplay . isHidden ( ) & &
( theNewDisplay . get_tab ( ) = = SHOW_STDDEV ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : handle_iqSelector ( ) {
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler ! = nullptr )
theOFDMHandler - > handle_iqSelector ( ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : showPeakLevel ( float iPeakLeft , float iPeakRight ) {
techWindow_p - > showPeakLevel ( iPeakLeft , iPeakRight ) ;
}
void RadioInterface : : handle_presetButton ( ) {
int mode = the_ensembleHandler - > get_showMode ( ) ;
if ( inputDevice_p - > isFileInput ( ) ) {
mode = SHOW_ENSEMBLE ;
presetButton - > setText ( " favorites " ) ;
the_ensembleHandler - > set_showMode ( mode ) ;
return ;
}
2024-03-13 19:45:53 +01:00
mode = mode = = SHOW_ENSEMBLE ? SHOW_PRESETS : SHOW_ENSEMBLE ;
2024-01-27 20:16:14 +01:00
the_ensembleHandler - > set_showMode ( mode ) ;
2024-04-19 18:34:50 +02:00
presetButton - > setText ( mode = = SHOW_ENSEMBLE ? " favorites " : " ensemble " ) ;
2024-01-27 20:16:14 +01:00
}
void RadioInterface : : set_soundLabel ( bool f ) {
QPixmap p ;
if ( f )
p . load ( " :res/volume_on.png " , " png " ) ;
else
p . load ( " :res/volume_off.png " , " png " ) ;
soundLabel - > setAlignment ( Qt : : AlignRight ) ;
soundLabel - >
setPixmap ( p . scaled ( 30 , 30 , Qt : : KeepAspectRatio ) ) ;
}
void RadioInterface : : handle_aboutLabel ( ) {
if ( the_aboutLabel = = nullptr ) {
the_aboutLabel = new AboutDialog ( nullptr ) ;
the_aboutLabel - > show ( ) ;
return ;
}
delete the_aboutLabel ;
the_aboutLabel = nullptr ;
}
//
// Starting a background task is by clicking with the right mouse button
// on the servicename, swrvice is known to be in current ensemble
void RadioInterface : : start_background_task ( const QString & service ) {
audiodata ad ;
2024-06-01 11:12:04 +02:00
theOFDMHandler - > data_for_audioservice ( service , ad ) ;
2024-01-27 20:16:14 +01:00
if ( ( ! ad . defined ) | | ( ad . ASCTy ! = 077 ) )
return ;
for ( uint16_t i = 0 ;
i < channel . backgroundServices . size ( ) ; i + + ) {
if ( channel . backgroundServices . at ( i ) . serviceName = =
service ) {
2024-06-01 11:12:04 +02:00
theOFDMHandler - > stop_service ( ad . subchId , BACK_GROUND ) ;
2024-01-27 20:16:14 +01:00
if ( channel . backgroundServices . at ( i ) . fd ! = nullptr )
fclose ( channel . backgroundServices . at ( i ) . fd ) ;
channel . backgroundServices . erase
( channel . backgroundServices . begin ( ) + i ) ;
return ;
}
}
2024-06-01 11:12:04 +02:00
FILE * f = theFilenameFinder . findFrameDump_fileName ( service , true ) ;
2024-01-27 20:16:14 +01:00
if ( f = = nullptr )
return ;
fprintf ( stderr , " starting a background job %s \n " ,
ad . serviceName . toLatin1 ( ) . data ( ) ) ;
2024-06-01 11:12:04 +02:00
( void ) theOFDMHandler - >
set_audioChannel ( ad , & theAudioBuffer , f , BACK_GROUND ) ;
2024-01-27 20:16:14 +01:00
dabService s ;
s . channel = ad . channel ;
s . serviceName = ad . serviceName ;
s . SId = ad . SId ;
s . SCIds = ad . SCIds ;
s . subChId = ad . subchId ;
s . fd = f ;
channel . backgroundServices . push_back ( s ) ;
}
2024-02-06 15:37:07 +01:00
void RadioInterface : : handle_labelColor ( ) {
QColor labelColor ;
QColor color = QColorDialog : : getColor ( labelColor ,
nullptr , " labelColor " ) ;
if ( ! color . isValid ( ) )
return ;
labelStyle = " color: " + color . name ( ) ;
2024-02-25 14:18:27 +01:00
dabSettings_p - > setValue ( LABEL_COLOR , labelStyle ) ;
2024-03-04 14:45:33 +01:00
QFont font = serviceLabel - > font ( ) ;
font . setPointSize ( 16 ) ;
font . setBold ( true ) ;
serviceLabel - > setStyleSheet ( labelStyle ) ;
serviceLabel - > setFont ( font ) ;
programTypeLabel - > setStyleSheet ( labelStyle ) ;
2024-02-13 10:22:47 +01:00
}
2024-02-25 14:18:27 +01:00
int RadioInterface : : int_configValue ( const QString & key , int d ) {
int val ;
val = dabSettings_p - > value ( key , d ) . toInt ( ) ;
return val ;
}
void RadioInterface : : show_dcOffset ( float dcOffset ) {
2024-06-01 11:12:04 +02:00
theNewDisplay . show_dcOffset ( dcOffset ) ;
2024-02-25 14:18:27 +01:00
}
void RadioInterface : : handle_techFrame_closed ( ) {
dabSettings_p - > setValue ( TECHDATA_VISIBLE , 0 ) ;
}
void RadioInterface : : handle_configFrame_closed ( ) {
dabSettings_p - > setValue ( CONFIG_WIDGET_VISIBLE , 0 ) ;
}
void RadioInterface : : handle_deviceFrame_closed ( ) {
dabSettings_p - > setValue ( DEVICE_WIDGET_VISIBLE , 0 ) ;
}
void RadioInterface : : handle_newDisplayFrame_closed ( ) {
dabSettings_p - > setValue ( NEW_DISPLAY_VISIBLE , 0 ) ;
}
2024-03-18 19:06:37 +01:00
void RadioInterface : : setVolume ( int n ) {
if ( n = = 0 )
set_soundLabel ( false ) ;
else
if ( channel . audioActive )
set_soundLabel ( true ) ;
( ( Qt_Audio * ) soundOut_p ) - > setVolume ( n ) ;
}
void RadioInterface : : handle_snrLabel ( ) {
2024-03-20 15:05:10 +01:00
if ( running . load ( ) ) {
dynamicLabel - > setStyleSheet ( labelStyle ) ;
QString SNR = " SNR " + QString : : number ( channel . snr ) ;
dynamicLabel - > setText ( SNR ) ;
}
2024-03-18 19:06:37 +01:00
}
2024-04-03 18:44:52 +02:00
void RadioInterface : : handle_correlationSelector ( int d ) {
( void ) d ;
bool b = configHandler_p - > get_correlationSelector ( ) ;
2024-04-15 14:03:12 +02:00
dabSettings_p - > setValue ( S_CORRELATION_ORDER , b ? 1 : 0 ) ;
2024-06-01 11:12:04 +02:00
if ( theOFDMHandler ! = nullptr )
theOFDMHandler - > set_correlationOrder ( b ) ;
2024-04-03 18:44:52 +02:00
}
void RadioInterface : : handle_dxSelector ( int d ) {
( void ) d ;
bool b = configHandler_p - > get_dxSelector ( ) ;
2024-04-15 14:03:12 +02:00
dabSettings_p - > setValue ( S_DX_MODE , b ? 1 : 0 ) ;
2024-04-04 15:13:56 +02:00
if ( ! b )
2024-06-01 11:12:04 +02:00
theDXDisplay . hide ( ) ;
if ( theOFDMHandler ! = nullptr )
theOFDMHandler - > set_dxMode ( b ) ;
2024-04-03 18:44:52 +02:00
if ( b )
distanceLabel - > setText ( " " ) ;
}
2024-04-16 15:18:29 +02:00
void RadioInterface : : channelSignal ( const QString & channel ) {
stopChannel ( ) ;
startChannel ( channel ) ;
}
2024-09-14 14:57:15 +02:00
void RadioInterface : : show_changeLabel ( const QStringList notInOld ,
const QStringList notInNew ) {
fprintf ( stderr , " A change in configuration occurred \n " ) ;
if ( notInOld . size ( ) > 0 ) {
fprintf ( stderr , " New service: \n " ) ;
for ( auto s : notInOld )
fprintf ( stderr , " \t %s \n " , s . toUtf8 ( ) . data ( ) ) ;
}
if ( notInNew . size ( ) > 0 ) {
fprintf ( stderr , " removed service: \n " ) ;
for ( auto s : notInNew )
fprintf ( stderr , " \t %s \n " , s . toUtf8 ( ) . data ( ) ) ;
}
}
2024-10-14 15:35:13 +02:00
void RadioInterface : : handle_folderButton ( ) {
QString tempPath = theFilenameFinder . basicPath ( ) ;
# ifdef __MINGW32__
ShellExecute ( nullptr , L " open " , tempPath . c_str ( ) ,
nullptr , nullptr , SW_SHOWDEFAULT ) ;
# else
std : : string x = " xdg-open " + tempPath . toStdString ( ) ;
fprintf ( stderr , " we gaan voor %s \n " , x . c_str ( ) ) ;
( void ) system ( x . c_str ( ) ) ;
# endif
}