Upstream version 2.10K

pull/2/head
Stelios Bounanos 2008-02-27 02:58:09 +00:00
rodzic ac64df5690
commit 28718230c5
19 zmienionych plików z 939 dodań i 772 usunięć

Wyświetl plik

@ -16,6 +16,8 @@ Change Log:
12) Fixes to mfsk picture mode decoding
13) Changed frequency2 data file format, downward compatible
14) Added FELD_SLOWHELL, FELD_HELLX5 and FELD_HELLX9 modems
15 Added support to the PortAudio backend for separate capture and playback
devices and sample rates
2.09 1) Modified src/Makefile.am for FreeBSD name space clash
2) Added psk multi-channel viewer with regex search capability

Wyświetl plik

@ -4,7 +4,7 @@
AC_COPYRIGHT([Copyright (C) 2007, 2008 Stelios Bounanos, M0GLD (m0gld AT enotty DOT net)])
AC_PREREQ(2.61)
AC_INIT([fldigi], [2.10J], [w1hkj AT w1hkj DOT com])
AC_INIT([fldigi], [2.10K], [w1hkj AT w1hkj DOT com])
AC_CONFIG_AUX_DIR([build-aux])
# define build, build_cpu, build_vendor, build_os
@ -121,7 +121,7 @@ AC_FLDIGI_PKG_CHECK([sndfile], [sndfile >= 1.0.10], [with], [SNDFILE],
# Set ac_cv_portaudio to yes/no
# Define USE_PORTAUDIO in config.h
# Substitute PORTAUDIO_CFLAGS and PORTAUDIO_LIBS in Makefile
AC_FLDIGI_PKG_CHECK([portaudio], [portaudio-2.0 >= 19], [without], [PORTAUDIO],
AC_FLDIGI_PKG_CHECK([portaudio], [portaudio-2.0 >= 19], [with], [PORTAUDIO],
[enable support for PortAudio @<:@autodetect@:>@] )
### pulseaudio
@ -134,7 +134,7 @@ AC_FLDIGI_PKG_CHECK([pulseaudio], [libpulse-simple >= 0.9.7], [with], [PULSEAUDI
if test "x$ac_cv_oss" = "xno" && \
test "x$ac_cv_portaudio" = "xno" && \
test "x$ac_cv_pulseaudio" = "xno"; then
AC_MSG_FAILURE([$PACKAGE requires OSS, PortAudio, or PulseAudio])
AC_MSG_WARN([*** $PACKAGE will be compiled without audio device support ***])
fi
### hamlib

Wyświetl plik

@ -556,6 +556,74 @@ Fl_Tabs *tabsSoundCard=(Fl_Tabs *)0;
Fl_Group *tabAudio=(Fl_Group *)0;
Fl_Group *AudioOSS=(Fl_Group *)0;
static void cb_btnAudioIO(Fl_Round_Button*, void*) {
update_sound_config(SND_IDX_OSS);
progdefaults.changed = true;
resetSoundCard();
}
Fl_Input_Choice *menuOSSDev=(Fl_Input_Choice *)0;
static void cb_menuOSSDev(Fl_Input_Choice* o, void*) {
scDevice[0] = scDevice[1] = progdefaults.OSSdevice = o->value();
resetSoundCard();
progdefaults.changed = true;
}
Fl_Group *AudioPort=(Fl_Group *)0;
static void cb_btnAudioIO1(Fl_Round_Button*, void*) {
update_sound_config(SND_IDX_PORT);
progdefaults.changed = true;
resetSoundCard();
}
Fl_Input_Choice *menuPortInDev=(Fl_Input_Choice *)0;
static void cb_menuPortInDev(Fl_Input_Choice* o, void*) {
scDevice[0] = progdefaults.PortInDevice = o->value();
resetSoundCard();
progdefaults.changed = true;
}
Fl_Input_Choice *menuPortOutDev=(Fl_Input_Choice *)0;
static void cb_menuPortOutDev(Fl_Input_Choice* o, void*) {
scDevice[1] = progdefaults.PortOutDevice = o->value();
resetSoundCard();
progdefaults.changed = true;
}
Fl_Group *AudioPulse=(Fl_Group *)0;
static void cb_btnAudioIO2(Fl_Round_Button*, void*) {
update_sound_config(SND_IDX_PULSE);
progdefaults.changed = true;
resetSoundCard();
}
Fl_Input *inpPulseServer=(Fl_Input *)0;
static void cb_inpPulseServer(Fl_Input* o, void*) {
scDevice[0] = scDevice[1] = progdefaults.PulseServer = o->value();
resetSoundCard();
progdefaults.changed = true;
}
Fl_Group *AudioNull=(Fl_Group *)0;
Fl_Round_Button *btnAudioIO[4]={(Fl_Round_Button *)0};
static void cb_btnAudioIO3(Fl_Round_Button*, void*) {
update_sound_config(SND_IDX_NULL);
progdefaults.changed = true;
resetSoundCard();
}
Fl_Group *tabAudioOpt=(Fl_Group *)0;
Fl_Spinner *cntRxRateCorr=(Fl_Spinner *)0;
static void cb_cntRxRateCorr(Fl_Spinner* o, void*) {
@ -577,69 +645,18 @@ static void cb_cntTxOffset(Fl_Spinner* o, void*) {
progdefaults.changed = true;
}
Fl_Group *AudioIO=(Fl_Group *)0;
Fl_Choice *menuOutSampleRate=(Fl_Choice *)0;
static void cb_btnAudioIO(Fl_Round_Button* o, void*) {
btnAudioIO[1]->value(0);
btnAudioIO[2]->value(0);
o->value(1);
menuOSSDev->activate();
menuPADev->deactivate();
menuSampleRate->deactivate();
scDevice = menuOSSDev->value();
progdefaults.btnAudioIOis = 0;
progdefaults.changed = true;
resetSoundCard();
}
static void cb_btnAudioIO1(Fl_Round_Button* o, void*) {
btnAudioIO[0]->value(0);
btnAudioIO[2]->value(0);
o->value(1);
menuPADev->activate();
menuOSSDev->deactivate();
menuSampleRate->activate();
scDevice = menuPADev->value();
progdefaults.btnAudioIOis = 1;
progdefaults.changed = true;
resetSoundCard();
}
Fl_Round_Button *btnAudioIO[3]={(Fl_Round_Button *)0};
static void cb_btnAudioIO2(Fl_Round_Button* o, void*) {
btnAudioIO[0]->value(0);
btnAudioIO[1]->value(0);
o->value(1);
menuPADev->deactivate();
menuOSSDev->deactivate();
menuSampleRate->deactivate();
scDevice = "localhost";
progdefaults.btnAudioIOis = 2;
progdefaults.changed = true;
resetSoundCard();
}
Fl_Input_Choice *menuOSSDev=(Fl_Input_Choice *)0;
static void cb_menuOSSDev(Fl_Input_Choice* o, void*) {
scDevice = progdefaults.OSSdevice = o->value();
static void cb_menuOutSampleRate(Fl_Choice* o, void*) {
progdefaults.out_sample_rate = o->value() > 1 ? strtol(o->mvalue()->text, 0, 10) : o->value();
resetSoundCard();
progdefaults.changed = true;
}
Fl_Input_Choice *menuPADev=(Fl_Input_Choice *)0;
Fl_Choice *menuInSampleRate=(Fl_Choice *)0;
static void cb_menuPADev(Fl_Input_Choice* o, void*) {
scDevice = progdefaults.PAdevice = o->value();
resetSoundCard();
progdefaults.changed = true;
}
Fl_Choice *menuSampleRate=(Fl_Choice *)0;
static void cb_menuSampleRate(Fl_Choice* o, void*) {
progdefaults.sample_rate = o->value() > 1 ? strtol(o->mvalue()->text, 0, 10) : o->value();
static void cb_menuInSampleRate(Fl_Choice* o, void*) {
progdefaults.in_sample_rate = o->value() > 1 ? strtol(o->mvalue()->text, 0, 10) : o->value();
resetSoundCard();
progdefaults.changed = true;
}
@ -887,8 +904,7 @@ progdefaults.changed = true;
Fl_Value_Slider *sldrHellBW=(Fl_Value_Slider *)0;
static void cb_sldrHellBW(Fl_Value_Slider*, void*) {
if (active_modem->get_mode() == MODE_FELDHELL)
active_modem->set_bandwidth(sldrHellBW->value());
active_modem->set_bandwidth(sldrHellBW->value());
progdefaults.changed = true;
}
@ -1151,7 +1167,7 @@ static const char szStopBits[] = "1|1.5|2";
static const char szOliviaTones[] = "2|4|8|16|32|64|128|256";
static const char szOliviaBandwidth[] = "125|250|500|1000|2000";
static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600|115200|230400|460800";
{ Fl_Double_Window* o = new Fl_Double_Window(400, 255, "fldigi - config");
{ Fl_Double_Window* o = new Fl_Double_Window(400, 254, "fldigi - config");
w = o;
o->color(FL_DARK2);
o->selection_color((Fl_Color)51);
@ -1539,6 +1555,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
{ Fl_Group* o = tabQRZ = new Fl_Group(0, 25, 400, 195, "qrz");
o->color((Fl_Color)51);
o->selection_color((Fl_Color)51);
o->hide();
{ Fl_Check_Button* o = btnQRZnotavailable = new Fl_Check_Button(31, 45, 200, 20, "Not available");
o->down_box(FL_DOWN_BOX);
o->value(1);
@ -1581,63 +1598,103 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
o->hide();
{ Fl_Tabs* o = tabsSoundCard = new Fl_Tabs(0, 25, 400, 195);
o->selection_color((Fl_Color)10);
{ Fl_Group* o = tabAudio = new Fl_Group(0, 50, 400, 170, "Audio");
{ Fl_Group* o = tabAudio = new Fl_Group(0, 50, 400, 170, "Audio devices");
o->color((Fl_Color)51);
o->selection_color((Fl_Color)51);
{ Fl_Spinner* o = cntRxRateCorr = new Fl_Spinner(300, 160, 75, 24, "RX ppm:");
{ Fl_Group* o = AudioOSS = new Fl_Group(5, 58, 391, 35);
o->box(FL_ENGRAVED_FRAME);
{ Fl_Round_Button* o = btnAudioIO[0] = new Fl_Round_Button(5, 63, 100, 25, "OSS");
o->down_box(FL_DIAMOND_DOWN_BOX);
o->selection_color((Fl_Color)1);
o->callback((Fl_Callback*)cb_btnAudioIO);
}
{ Fl_Input_Choice* o = menuOSSDev = new Fl_Input_Choice(280, 63, 110, 25, "Device");
o->callback((Fl_Callback*)cb_menuOSSDev);
o->value(progdefaults.OSSdevice.c_str());
}
o->end();
}
{ Fl_Group* o = AudioPort = new Fl_Group(5, 95, 390, 61);
o->box(FL_ENGRAVED_FRAME);
{ Fl_Round_Button* o = btnAudioIO[1] = new Fl_Round_Button(5, 115, 95, 25, "PortAudio");
o->down_box(FL_DIAMOND_DOWN_BOX);
o->selection_color((Fl_Color)1);
o->callback((Fl_Callback*)cb_btnAudioIO1);
}
{ Fl_Input_Choice* o = menuPortInDev = new Fl_Input_Choice(165, 99, 225, 25, "Capture");
o->callback((Fl_Callback*)cb_menuPortInDev);
o->value(progdefaults.PortInDevice.c_str());
}
{ Fl_Input_Choice* o = menuPortOutDev = new Fl_Input_Choice(165, 127, 225, 25, "Playback");
o->callback((Fl_Callback*)cb_menuPortOutDev);
o->value(progdefaults.PortOutDevice.c_str());
}
o->end();
}
{ Fl_Group* o = AudioPulse = new Fl_Group(5, 158, 390, 32);
o->box(FL_ENGRAVED_FRAME);
{ Fl_Round_Button* o = btnAudioIO[2] = new Fl_Round_Button(5, 159, 100, 30, "PulseAudio");
o->down_box(FL_DIAMOND_DOWN_BOX);
o->selection_color((Fl_Color)1);
o->callback((Fl_Callback*)cb_btnAudioIO2);
}
{ Fl_Input* o = inpPulseServer = new Fl_Input(165, 161, 225, 25, "Server");
o->tooltip("Leave this blank or refer to\nhttp://www.pulseaudio.org/wiki/ServerStrings");
o->callback((Fl_Callback*)cb_inpPulseServer);
o->value(progdefaults.PulseServer.c_str());
}
o->end();
}
{ Fl_Group* o = AudioNull = new Fl_Group(5, 192, 390, 25);
o->box(FL_ENGRAVED_FRAME);
{ Fl_Round_Button* o = btnAudioIO[3] = new Fl_Round_Button(5, 192, 100, 25, "File I/O only");
o->down_box(FL_DIAMOND_DOWN_BOX);
o->selection_color((Fl_Color)1);
o->callback((Fl_Callback*)cb_btnAudioIO3);
}
o->end();
}
o->end();
}
{ Fl_Group* o = tabAudioOpt = new Fl_Group(0, 50, 400, 170, "Audio settings");
o->color((Fl_Color)51);
o->selection_color((Fl_Color)51);
o->hide();
{ Fl_Spinner* o = cntRxRateCorr = new Fl_Spinner(5, 160, 85, 25, "RX ppm");
o->callback((Fl_Callback*)cb_cntRxRateCorr);
o->align(FL_ALIGN_RIGHT);
o->step(1);
o->minimum(-50000);
o->maximum(50000);
}
{ Fl_Spinner* o = cntTxRateCorr = new Fl_Spinner(300, 130, 75, 24, "TX ppm:");
{ Fl_Spinner* o = cntTxRateCorr = new Fl_Spinner(5, 130, 85, 25, "TX ppm");
o->callback((Fl_Callback*)cb_cntTxRateCorr);
o->align(FL_ALIGN_RIGHT);
o->step(1);
o->minimum(-50000);
o->maximum(50000);
}
{ Fl_Spinner* o = cntTxOffset = new Fl_Spinner(330, 190, 45, 24, "Tx offset:");
{ Fl_Spinner* o = cntTxOffset = new Fl_Spinner(5, 190, 85, 25, "TX offset");
o->callback((Fl_Callback*)cb_cntTxOffset);
o->align(FL_ALIGN_RIGHT);
o->value(progdefaults.TxOffset);
o->step(1);
o->minimum(-50);
o->maximum(50);
}
{ Fl_Group* o = AudioIO = new Fl_Group(0, 55, 140, 70, "I/O");
o->box(FL_ENGRAVED_FRAME);
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
{ Fl_Round_Button* o = btnAudioIO[0] = new Fl_Round_Button(35, 60, 100, 25, "OSS");
o->down_box(FL_DIAMOND_DOWN_BOX);
o->selection_color((Fl_Color)1);
o->callback((Fl_Callback*)cb_btnAudioIO);
}
{ Fl_Round_Button* o = btnAudioIO[1] = new Fl_Round_Button(35, 80, 100, 25, "PortAudio");
o->down_box(FL_DIAMOND_DOWN_BOX);
o->selection_color((Fl_Color)1);
o->callback((Fl_Callback*)cb_btnAudioIO1);
}
{ Fl_Round_Button* o = btnAudioIO[2] = new Fl_Round_Button(35, 100, 100, 25, "PulseAudio");
o->down_box(FL_DIAMOND_DOWN_BOX);
o->selection_color((Fl_Color)1);
o->callback((Fl_Callback*)cb_btnAudioIO2);
}
o->end();
}
{ Fl_Input_Choice* o = menuOSSDev = new Fl_Input_Choice(155, 60, 110, 25, "OSS device");
o->callback((Fl_Callback*)cb_menuOSSDev);
o->align(FL_ALIGN_RIGHT);
o->value(progdefaults.OSSdevice.c_str());
}
{ Fl_Input_Choice* o = menuPADev = new Fl_Input_Choice(155, 90, 110, 25, "PortAudio device");
o->callback((Fl_Callback*)cb_menuPADev);
o->align(FL_ALIGN_RIGHT);
o->value(progdefaults.PAdevice.c_str());
}
{ Fl_Choice* o = menuSampleRate = new Fl_Choice(5, 190, 85, 25, "Sample rate");
{ Fl_Choice* o = menuOutSampleRate = new Fl_Choice(5, 90, 85, 25, "Playback sample rate");
o->tooltip("Force a specific sample rate. Select \"Native\" if \"Auto\" does not work wel\
l with your sound hardware.");
o->down_box(FL_BORDER_BOX);
o->callback((Fl_Callback*)cb_menuSampleRate);
o->callback((Fl_Callback*)cb_menuOutSampleRate);
o->align(FL_ALIGN_RIGHT);
o->menu(sample_rate_menu);
}
{ Fl_Choice* o = menuInSampleRate = new Fl_Choice(5, 60, 85, 25, "Capture sample rate");
o->tooltip("Force a specific sample rate. Select \"Native\" if \"Auto\" does not work wel\
l with your sound hardware.");
o->down_box(FL_BORDER_BOX);
o->callback((Fl_Callback*)cb_menuInSampleRate);
o->align(FL_ALIGN_RIGHT);
o->menu(sample_rate_menu);
}
@ -1731,7 +1788,6 @@ fect after a restart.");
{ Fl_Group* o = tabModems = new Fl_Group(0, 25, 401, 195, "Modem");
o->color((Fl_Color)51);
o->selection_color((Fl_Color)51);
o->hide();
{ Fl_Tabs* o = tabsModems = new Fl_Tabs(0, 25, 401, 195);
o->color((Fl_Color)51);
o->selection_color((Fl_Color)10);
@ -1911,7 +1967,6 @@ fect after a restart.");
{ Fl_Group* o = tabFeld = new Fl_Group(0, 50, 400, 170, "Feld");
o->color((Fl_Color)51);
o->selection_color((Fl_Color)51);
o->hide();
{ Fl_Choice* o = selHellFont = new Fl_Choice(175, 62, 122, 20, "Feld Hell Font:");
o->down_box(FL_BORDER_BOX);
o->labelfont(4);
@ -1923,10 +1978,10 @@ fect after a restart.");
{ Fl_Value_Slider* o = sldrHellBW = new Fl_Value_Slider(30, 190, 345, 20, "Filter BW");
o->type(1);
o->color((Fl_Color)215);
o->minimum(50);
o->maximum(600);
o->minimum(10);
o->maximum(2400);
o->step(5);
o->value(245);
o->value(400);
o->textsize(14);
o->callback((Fl_Callback*)cb_sldrHellBW);
o->align(FL_ALIGN_TOP_LEFT);
@ -2042,6 +2097,7 @@ fect after a restart.");
o->end();
}
{ Fl_Group* o = new Fl_Group(0, 50, 400, 170, "PskViewer");
o->hide();
{ Fl_Group* o = new Fl_Group(5, 60, 390, 155);
o->box(FL_ENGRAVED_FRAME);
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);

Wyświetl plik

@ -35,14 +35,14 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
code {} {}
Fl_Window {} {
label {fldigi - config} open
xywh {663 306 400 255} type Double color 45 selection_color 51 align 80 visible
xywh {868 365 400 254} type Double color 45 selection_color 51 align 80 visible
} {
Fl_Tabs tabsConfigure {open
xywh {0 0 405 220} color 47 selection_color 9
} {
Fl_Group tabOperator {
label Oper
callback {progdefaults.changed = true;} open
callback {progdefaults.changed = true;}
xywh {0 25 400 195} color 51 selection_color 51 when 1 hide
} {
Fl_Input inpMyCallsign {
@ -89,7 +89,7 @@ progdefaults.changed = true;}
}
}
Fl_Group tabWaterfall {
label {W-fall} open
label {W-fall}
xywh {0 25 405 195} color 51 selection_color 51 hide
} {
Fl_Tabs {} {open
@ -306,7 +306,7 @@ progdefaults.changed = true;
}
}
Fl_Group tabVideo {
label Video open
label Video
xywh {0 25 400 195} color 51 selection_color 51 hide
} {
Fl_Group {} {
@ -369,7 +369,7 @@ progdefaults.changed = true;}
}
}
Fl_Group tabRig {
label Rig open
label Rig
xywh {0 25 400 195} hide
} {
Fl_Group {} {
@ -578,7 +578,7 @@ progdefaults.changed = true;}
}
Fl_Group tabQRZ {
label qrz open
xywh {0 25 400 195} color 51 selection_color 51
xywh {0 25 400 195} color 51 selection_color 51 hide
} {
Fl_Check_Button btnQRZnotavailable {
label {Not available}
@ -600,7 +600,7 @@ btnQRZnotavailable->value(0);
btnHAMCALLsocket->value(0);
progdefaults.QRZ = 1;
}
progdefaults.changed = true;} selected
progdefaults.changed = true;}
tooltip {You need a QRZ on-line subscription to access QRZ.com} xywh {32 74 205 20} down_box DOWN_BOX
code0 {if (progdefaults.QRZ == 1) o->value(1); else o->value(0);}
}
@ -658,112 +658,140 @@ o->label((inpQRZuserpassword->type() & FL_SECRET_INPUT) ? "Show" : "Hide");}
xywh {0 25 400 195} selection_color 10
} {
Fl_Group tabAudio {
label Audio open
label {Audio devices} open
xywh {0 50 400 170} color 51 selection_color 51
} {
Fl_Group AudioOSS {open
xywh {5 58 391 35} box ENGRAVED_FRAME
} {
Fl_Round_Button {btnAudioIO[0]} {
label OSS
callback {update_sound_config(SND_IDX_OSS);
progdefaults.changed = true;
resetSoundCard();} selected
xywh {5 63 100 25} down_box DIAMOND_DOWN_BOX selection_color 1
}
Fl_Input_Choice menuOSSDev {
label Device
callback {scDevice[0] = scDevice[1] = progdefaults.OSSdevice = o->value();
resetSoundCard();
progdefaults.changed = true;} open
xywh {280 63 110 25}
code0 {o->value(progdefaults.OSSdevice.c_str());}
} {}
}
Fl_Group AudioPort {open
xywh {5 95 390 61} box ENGRAVED_FRAME
} {
Fl_Round_Button {btnAudioIO[1]} {
label PortAudio
callback {update_sound_config(SND_IDX_PORT);
progdefaults.changed = true;
resetSoundCard();}
xywh {5 115 95 25} down_box DIAMOND_DOWN_BOX selection_color 1
}
Fl_Input_Choice menuPortInDev {
label Capture
callback {scDevice[0] = progdefaults.PortInDevice = o->value();
resetSoundCard();
progdefaults.changed = true;} open
xywh {165 99 225 25}
code0 {o->value(progdefaults.PortInDevice.c_str());}
} {}
Fl_Input_Choice menuPortOutDev {
label Playback
callback {scDevice[1] = progdefaults.PortOutDevice = o->value();
resetSoundCard();
progdefaults.changed = true;} open
xywh {165 127 225 25}
code0 {o->value(progdefaults.PortOutDevice.c_str());}
} {}
}
Fl_Group AudioPulse {open
xywh {5 158 390 32} box ENGRAVED_FRAME
} {
Fl_Round_Button {btnAudioIO[2]} {
label PulseAudio
callback {update_sound_config(SND_IDX_PULSE);
progdefaults.changed = true;
resetSoundCard();}
xywh {5 159 100 30} down_box DIAMOND_DOWN_BOX selection_color 1
}
Fl_Input inpPulseServer {
label Server
callback {scDevice[0] = scDevice[1] = progdefaults.PulseServer = o->value();
resetSoundCard();
progdefaults.changed = true;}
tooltip {Leave this blank or refer to
http://www.pulseaudio.org/wiki/ServerStrings} xywh {165 161 225 25}
code0 {o->value(progdefaults.PulseServer.c_str());}
}
}
Fl_Group AudioNull {open
xywh {5 192 390 25} box ENGRAVED_FRAME
} {
Fl_Round_Button {btnAudioIO[3]} {
label {File I/O only}
callback {update_sound_config(SND_IDX_NULL);
progdefaults.changed = true;
resetSoundCard();}
xywh {5 192 100 25} down_box DIAMOND_DOWN_BOX selection_color 1
}
}
}
Fl_Group tabAudioOpt {
label {Audio settings} open
xywh {0 50 400 170} color 51 selection_color 51 hide
} {
Fl_Spinner cntRxRateCorr {
label {RX ppm:}
label {RX ppm}
callback {progdefaults.RX_corr = (int)o->value();
progdefaults.changed = true;}
xywh {300 160 75 24}
xywh {5 160 85 25} align 8
code0 {o->step(1);}
code1 {o->minimum(-50000);}
code2 {o->maximum(50000);}
}
Fl_Spinner cntTxRateCorr {
label {TX ppm:}
label {TX ppm}
callback {progdefaults.TX_corr = (int)o->value();
progdefaults.changed = true;}
xywh {300 130 75 24}
xywh {5 130 85 25} align 8
code0 {o->step(1);}
code1 {o->minimum(-50000);}
code2 {o->maximum(50000);}
}
Fl_Spinner cntTxOffset {
label {Tx offset:}
label {TX offset}
callback {progdefaults.TxOffset = (int)o->value();
progdefaults.changed = true;}
xywh {330 190 45 24}
xywh {5 190 85 25} align 8
code0 {o->value(progdefaults.TxOffset);}
code1 {o->step(1);}
code2 {o->minimum(-50);}
code3 {o->maximum(50);}
}
Fl_Group AudioIO {
label {I/O} open
xywh {0 55 140 70} box ENGRAVED_FRAME align 21
} {
Fl_Round_Button {btnAudioIO[0]} {
label OSS
callback {btnAudioIO[1]->value(0);
btnAudioIO[2]->value(0);
o->value(1);
menuOSSDev->activate();
menuPADev->deactivate();
menuSampleRate->deactivate();
scDevice = menuOSSDev->value();
progdefaults.btnAudioIOis = 0;
progdefaults.changed = true;
resetSoundCard();}
xywh {35 60 100 25} down_box DIAMOND_DOWN_BOX selection_color 1
}
Fl_Round_Button {btnAudioIO[1]} {
label PortAudio
callback {btnAudioIO[0]->value(0);
btnAudioIO[2]->value(0);
o->value(1);
menuPADev->activate();
menuOSSDev->deactivate();
menuSampleRate->activate();
scDevice = menuPADev->value();
progdefaults.btnAudioIOis = 1;
progdefaults.changed = true;
resetSoundCard();}
xywh {35 80 100 25} down_box DIAMOND_DOWN_BOX selection_color 1
}
Fl_Round_Button {btnAudioIO[2]} {
label PulseAudio
callback {btnAudioIO[0]->value(0);
btnAudioIO[1]->value(0);
o->value(1);
menuPADev->deactivate();
menuOSSDev->deactivate();
menuSampleRate->deactivate();
scDevice = "localhost";
progdefaults.btnAudioIOis = 2;
progdefaults.changed = true;
resetSoundCard();}
xywh {35 100 100 25} down_box DIAMOND_DOWN_BOX selection_color 1
}
}
Fl_Input_Choice menuOSSDev {
label {OSS device}
callback {scDevice = progdefaults.OSSdevice = o->value();
Fl_Choice menuOutSampleRate {
label {Playback sample rate}
callback {progdefaults.out_sample_rate = o->value() > 1 ? strtol(o->mvalue()->text, 0, 10) : o->value();
resetSoundCard();
progdefaults.changed = true;} open
xywh {155 60 110 25} align 8
code0 {o->value(progdefaults.OSSdevice.c_str());}
tooltip {Force a specific sample rate. Select "Native" if "Auto" does not work well with your sound hardware.} xywh {5 90 85 25} down_box BORDER_BOX align 8
code0 {extern Fl_Menu_Item sample_rate_menu[];}
code1 {o->menu(sample_rate_menu);}
} {}
Fl_Input_Choice menuPADev {
label {PortAudio device}
callback {scDevice = progdefaults.PAdevice = o->value();
Fl_Choice menuInSampleRate {
label {Capture sample rate}
callback {progdefaults.in_sample_rate = o->value() > 1 ? strtol(o->mvalue()->text, 0, 10) : o->value();
resetSoundCard();
progdefaults.changed = true;} open
xywh {155 90 110 25} align 8
code0 {o->value(progdefaults.PAdevice.c_str());}
} {}
Fl_Choice menuSampleRate {
label {Sample rate}
callback {progdefaults.sample_rate = o->value() > 1 ? strtol(o->mvalue()->text, 0, 10) : o->value();
resetSoundCard();
progdefaults.changed = true;} open
tooltip {Force a specific sample rate. Select "Native" if "Auto" does not work well with your sound hardware.} xywh {5 190 85 25} down_box BORDER_BOX align 8
tooltip {Force a specific sample rate. Select "Native" if "Auto" does not work well with your sound hardware.} xywh {5 60 85 25} down_box BORDER_BOX align 8
code0 {extern Fl_Menu_Item sample_rate_menu[];}
code1 {o->menu(sample_rate_menu);}
} {}
}
Fl_Group tabMixer {
label Mixer open
label Mixer
xywh {0 50 400 170} color 51 selection_color 51 hide
} {
Fl_Light_Button btnLineIn {
@ -869,7 +897,7 @@ This option takes effect after a restart.} xywh {50 155 180 20} down_box DOWN_BO
}
Fl_Group tabModems {
label Modem open
xywh {0 25 401 195} color 51 selection_color 51 hide
xywh {0 25 401 195} color 51 selection_color 51
} {
Fl_Tabs tabsModems {open
xywh {0 25 401 195} color 51 selection_color 10 align 9
@ -1024,7 +1052,7 @@ progdefaults.changed = true;}
}
Fl_Group tabFeld {
label Feld open
xywh {0 50 400 170} color 51 selection_color 51 hide
xywh {0 50 400 170} color 51 selection_color 51
} {
Fl_Choice selHellFont {
label {Feld Hell Font:}
@ -1037,10 +1065,9 @@ progdefaults.changed = true;} open
} {}
Fl_Value_Slider sldrHellBW {
label {Filter BW}
callback {if (active_modem->get_mode() == MODE_FELDHELL)
active_modem->set_bandwidth(sldrHellBW->value());
progdefaults.changed = true;}
xywh {30 190 345 20} type Horizontal color 215 align 5 minimum 50 maximum 600 step 5 value 245 textsize 14
callback {active_modem->set_bandwidth(sldrHellBW->value());
progdefaults.changed = true;} selected
xywh {30 190 345 20} type Horizontal color 215 align 5 minimum 10 maximum 2400 step 5 value 400 textsize 14
}
Fl_Check_Button btnHellXmtWidth {
label {2x Xmt Width}
@ -1161,7 +1188,7 @@ progdefaults.changed = true;}
}
Fl_Group {} {
label PskViewer open
xywh {0 50 400 170}
xywh {0 50 400 170} hide
} {
Fl_Group {} {open
xywh {5 60 390 155} box ENGRAVED_FRAME align 21

Wyświetl plik

@ -226,6 +226,7 @@ void startup_modem(modem *m)
m == feld_80modem ) {
ReceiveText->Hide();
FHdisp->show();
sldrHellBW->value(m->get_bandwidth());
} else {
ReceiveText->Show();
FHdisp->hide();
@ -1694,13 +1695,13 @@ void put_echo_char(unsigned int data)
void resetRTTY() {
if (active_modem->get_mode() != MODE_RTTY) return;
trx_reset(scDevice.c_str());
trx_reset();
active_modem->restart();
}
void resetOLIVIA() {
if (active_modem->get_mode() != MODE_OLIVIA) return;
trx_reset(scDevice.c_str());
trx_reset();
active_modem->restart();
}
@ -1713,7 +1714,7 @@ void resetDOMEX() {
md == MODE_DOMINOEX16 ||
md == MODE_DOMINOEX22 ) {
trx_reset(scDevice.c_str());
trx_reset();
active_modem->restart();
}
}
@ -1823,12 +1824,53 @@ void resetSoundCard()
{
bool mixer_enabled = progdefaults.EnableMixer;
enableMixer(false);
trx_reset(scDevice.c_str());
progdefaults.SCdevice = scDevice;
trx_reset();
if (mixer_enabled)
enableMixer(true);
}
void update_sound_config(unsigned idx)
{
// radio button
for (size_t i = 0; i < sizeof(btnAudioIO)/sizeof(*btnAudioIO); i++)
btnAudioIO[i]->value(i == idx);
// devices
menuOSSDev->deactivate();
menuPortInDev->deactivate();
menuPortOutDev->deactivate();
inpPulseServer->deactivate();
// settings
menuInSampleRate->deactivate();
menuOutSampleRate->deactivate();
progdefaults.btnAudioIOis = idx;
switch (idx) {
case SND_IDX_OSS:
menuOSSDev->activate();
scDevice[0] = scDevice[1] = menuOSSDev->value();
break;
case SND_IDX_PORT:
menuPortInDev->activate();
menuPortOutDev->activate();
menuInSampleRate->activate();
menuOutSampleRate->activate();
scDevice[0] = menuPortInDev->value();
scDevice[1] = menuPortOutDev->value();
break;
case SND_IDX_PULSE:
inpPulseServer->activate();
menuInSampleRate->activate();
menuOutSampleRate->activate();
scDevice[0] = scDevice[1] = inpPulseServer->value();
break;
case SND_IDX_NULL:
scDevice[0] = scDevice[1] = "";
break;
};
}
void setReverse(int rev) {
active_modem->set_reverse(rev);
}

Wyświetl plik

@ -39,6 +39,9 @@
#include "confdialog.h"
#include "qrunner.h"
#include <FL/Fl.H>
#include <FL/Fl_Value_Slider.H>
char feldmsg[80];
void feld::tx_init(SoundBase *sc)
@ -85,59 +88,50 @@ feld::feld(trx_mode m)
double lp;
mode = m;
samplerate = FeldSampleRate;
FL_LOCK_D();
bandwidth = sldrHellBW->value();
FL_UNLOCK_D();
switch (mode) {
case MODE_FSKHELL:
bandwidth = 122.5;
feldcolumnrate = 17.5;
break;
switch (mode) {
// Amplitude modulation modes
case MODE_FELDHELL:
feldcolumnrate = 17.5;
break;
case MODE_SLOWHELL:
bandwidth = 122.5;
// bandwidth = 50;
feldcolumnrate = 2.1875;
break;
case MODE_HELLX5:
bandwidth = 1000;
feldcolumnrate = 87.5;
break;
case MODE_HELLX9:
bandwidth = 2000;
feldcolumnrate = 157.5;
break;
// Frequency modulation modes
case MODE_FSKHELL:
feldcolumnrate = 17.5;
break;
case MODE_FSKH105:
bandwidth = 55;
feldcolumnrate = 17.5;
break;
case MODE_HELL80:
bandwidth = 300;
feldcolumnrate = 35;
break;
case MODE_FELDHELL:
default :
bandwidth = 122.5;
feldcolumnrate = 17.5;
break;
}
hell_bandwidth = bandwidth;
rxpixrate = (RxColumnLen * feldcolumnrate);
txpixrate = (TxColumnLen * feldcolumnrate);
downsampleinc = (double)(rxpixrate/samplerate);
upsampleinc = (double)(txpixrate/samplerate);
phi2freq = samplerate / txpixrate / 2.0 / M_PI;
hell_bandwidth = txpixrate;
hell_bandwidth = bandwidth;
set_bandwidth(hell_bandwidth);
hilbert = new C_FIR_filter();
hilbert->init_hilbert(37, 1);
if (mode == MODE_FELDHELL || mode == MODE_SLOWHELL ||
mode == MODE_HELLX5 || mode == MODE_HELLX9 )
lp = 1.5 * bandwidth / 2.0 / samplerate;
else
lp = 1.5 * txpixrate / samplerate;
lp = 1.5 * bandwidth / samplerate;
bpfilt = new fftfilt(0, lp, 1024);
@ -181,7 +175,7 @@ void feld::FSKHELL_rx(complex z)
double f;
int vid;
f = (prev % z).arg() * samplerate / M_PI / bandwidth / 2.0;
f = (prev % z).arg() * phi2freq;
prev = z;
f = bbfilt->run(f);
@ -275,20 +269,20 @@ int feld::rx_process(const double *buf, int len)
// squelchon = progdefaults.sqlonoff;
FL_UNLOCK_D();
switch (mode) {
default:
// switch (mode) {
// default:
if (bandwidth != hell_bandwidth) {
double lp;
hell_bandwidth = bandwidth;
lp = 1.5 * bandwidth / 2.0 / samplerate;
bpfilt->create_filter(0, lp);
}
break;
case MODE_FSKHELL:
case MODE_FSKH105:
case MODE_HELL80:
break;
}
// break;
// case MODE_FSKHELL:
// case MODE_FSKH105:
// case MODE_HELL80:
// break;
// }
while (len-- > 0) {
/* create analytic signal... */
@ -394,10 +388,10 @@ void feld::send_symbol(int currsymb, int nextsymb)
switch (mode) {
case MODE_FSKHELL :
case MODE_FSKH105 :
tone = midtone + (reverse ? -1 : 1) * (currsymb ? -1 : 1) * bandwidth / 2.0;
tone = midtone + (reverse ? -1 : 1) * (currsymb ? -1 : 1) * txpixrate / 2.0;
break;
case MODE_HELL80:
tone = midtone - (reverse ? -1 : 1) * (currsymb ? -1 : 1) * bandwidth / 2.0;
tone = midtone - (reverse ? -1 : 1) * (currsymb ? -1 : 1) * txpixrate / 2.0;
break;
case MODE_HELLX5 : case MODE_HELLX9 :
Amp = currsymb;

Wyświetl plik

@ -81,17 +81,24 @@ extern Fl_Button *btnQRZpasswordShow;
extern Fl_Group *tabSoundCard;
extern Fl_Tabs *tabsSoundCard;
extern Fl_Group *tabAudio;
extern Fl_Group *AudioOSS;
#include <FL/Fl_Input_Choice.H>
extern Fl_Input_Choice *menuOSSDev;
extern Fl_Group *AudioPort;
extern Fl_Input_Choice *menuPortInDev;
extern Fl_Input_Choice *menuPortOutDev;
extern Fl_Group *AudioPulse;
extern Fl_Input *inpPulseServer;
extern Fl_Group *AudioNull;
extern Fl_Round_Button *btnAudioIO[4];
extern Fl_Group *tabAudioOpt;
#include <FL/Fl_Spinner.H>
extern Fl_Spinner *cntRxRateCorr;
extern Fl_Spinner *cntTxRateCorr;
extern Fl_Spinner *cntTxOffset;
extern Fl_Group *AudioIO;
extern Fl_Round_Button *btnAudioIO[3];
#include <FL/Fl_Input_Choice.H>
extern Fl_Input_Choice *menuOSSDev;
extern Fl_Input_Choice *menuPADev;
extern Fl_Menu_Item sample_rate_menu[];
extern Fl_Choice *menuSampleRate;
extern Fl_Choice *menuOutSampleRate;
extern Fl_Choice *menuInSampleRate;
extern Fl_Group *tabMixer;
#include <FL/Fl_Light_Button.H>
extern void setMixerInput(int);

Wyświetl plik

@ -130,10 +130,14 @@ struct configuration {
string secText;
// Sound card
int btnAudioIOis;
string SCdevice;
string OSSdevice;
string PAdevice;
string PortInDevice;
string PortOutDevice;
string PulseServer;
int sample_rate;
int in_sample_rate;
int out_sample_rate;
string sample_converter;
int RX_corr;
int TX_corr;

Wyświetl plik

@ -59,14 +59,12 @@ protected:
double txpixrate;
double downsampleinc;
double upsampleinc;
double phi2freq;
C_FIR_filter *hilbert;
fftfilt *bpfilt;
Cmovavg *bbfilt;
Cmovavg *minmaxfilt;
// double bbfilter[MaxSymLen];
// unsigned int filterptr;
//tx
FELD_STATE tx_state;
double txphacc;

Wyświetl plik

@ -129,6 +129,7 @@ extern void resetRTTY();
extern void resetOLIVIA();
extern void resetDOMEX();
extern void resetSoundCard();
extern void update_sound_config(unsigned idx);
extern void restoreFocus();
extern void setReverse(int);
extern void clearQSO();

Wyświetl plik

@ -24,7 +24,7 @@
extern string HomeDir;
extern string xmlfname;
extern std::string scDevice;
extern std::string scDevice[2];
extern PTT *push2talk;
#if USE_HAMLIB
extern Rig *xcvr;

Wyświetl plik

@ -28,6 +28,8 @@
#ifndef _SOUND_H
#define _SOUND_H
enum { SND_IDX_UNKNOWN = -1, SND_IDX_OSS, SND_IDX_PORT, SND_IDX_PULSE, SND_IDX_NULL, SND_IDX_END };
#include <cstring>
#include <string>
#include <vector>
@ -55,15 +57,20 @@
class SndException : public std::exception
{
public:
SndException(int err_ = 0) : err(err_), msg(std::string("Sound error: ") + err_to_str()) { }
SndException(const char* msg_) : err(1), msg(msg_) { }
SndException(int err_ = 0)
: err(err_), msg(std::string("Sound error: ") + err_to_str(err_))
{ }
SndException(const char* msg_)
: err(1), msg(msg_)
{ }
SndException(int err_, const std::string& msg_) : err(err_), msg(msg_) { }
virtual ~SndException() throw() { }
const char* what(void) const throw() { return msg.c_str(); }
int error(void) const { return err; }
protected:
virtual const char* err_to_str(void) { return strerror(err); }
const char* err_to_str(int e) { return strerror(e); }
int err;
std::string msg;
@ -73,10 +80,12 @@ protected:
class SndPortException : public SndException
{
public:
SndPortException(int err_ = 0) : SndException(err_) { }
SndPortException(int err_ = 0)
: SndException(err_, std::string("PortAudio error: ") + err_to_str(err_))
{ }
SndPortException(const char* msg_) : SndException(msg_) { }
protected:
const char* err_to_str(void) { return Pa_GetErrorText(err); }
const char* err_to_str(int e) { return Pa_GetErrorText(e); }
};
#endif
@ -84,10 +93,12 @@ protected:
class SndPulseException : public SndException
{
public:
SndPulseException(int err_ = 0) : SndException(err_) { }
SndPulseException(int err_ = 0)
: SndException(err_, std::string("PulseAudio error: ") + err_to_str(err_))
{ }
SndPulseException(const char* msg_) : SndException(msg_) { }
protected:
const char* err_to_str(void) { return pa_strerror(err); }
const char* err_to_str(int e) { return pa_strerror(e); }
};
#endif
@ -203,7 +214,7 @@ public:
static const std::vector<const PaDeviceInfo*>& devices(void);
public:
SoundPort(const char *dev);
SoundPort(const char *in_dev, const char *out_dev);
~SoundPort();
int Open(int mode, int freq = 8000);
void Close();
@ -215,31 +226,27 @@ public:
private:
void src_data_reset(int mode);
void resample(int mode, float *buf, size_t count, size_t max = 0);
void init_stream(void);
void start_stream(void);
bool stream_active(void);
void init_stream(unsigned dir);
void start_stream(unsigned dir);
bool stream_active(unsigned dir);
bool full_duplex_device(const PaDeviceInfo* dev);
bool adjust_stream(void);
double find_srate(void);
double find_srate(unsigned dir);
void pa_perror(int err, const char* str = 0);
private:
std::string device;
enum { STREAM_IN, STREAM_OUT };
std::string device[2];
static bool pa_init;
PaStream* stream;
PaStream* stream[2];
device_iterator idev;
device_iterator idev[2];
static std::vector<const PaDeviceInfo*> devs;
PaStreamParameters in_params;
PaStreamParameters out_params;
enum { STREAM_IN, STREAM_OUT };
PaStreamParameters* stream_params[2];
PaStreamParameters stream_params[2];
unsigned frames_per_buffer;
unsigned max_frames_per_buffer;
unsigned frames_per_buffer[2];
double req_sample_rate;
double dev_sample_rate;
double dev_sample_rate[2];
float *fbuf;
};
@ -265,9 +272,8 @@ private:
void resample(int mode, float *buf, size_t count, size_t max = 0);
private:
double dev_sample_rate;
pa_simple* in_stream;
pa_simple* out_stream;
double dev_sample_rate[2];
pa_simple* stream[2];
pa_sample_spec stream_params;
float* fbuf;
@ -275,4 +281,16 @@ private:
#endif // USE_PULSEAUDIO
class SoundNull : public SoundBase
{
public:
int Open(int mode, int freq = 8000) { sample_frequency = freq; return 0; }
void Close(void) { }
size_t Write(double* buf, size_t count);
size_t Write_stereo(double* bufleft, double* bufright, size_t count);
size_t Read(double *buf, size_t count);
bool full_duplex(void) { return true; }
};
#endif // SOUND_H

Wyświetl plik

@ -37,9 +37,9 @@
// ----------------------------------------------------------------------------
extern void trx_start_modem(modem *);
extern void trx_start(const char *scdev);
extern void trx_start(void);
extern void trx_close();
extern void trx_reset(const char *scdev);
extern void trx_reset(void);
extern void trx_start_macro_timer();
extern void wait_modem_ready_prep(void);

Wyświetl plik

@ -68,7 +68,7 @@
using namespace std;
string scDevice = "/dev/dsp1";
string scDevice[2];
bool pa_allow_full_duplex = false;
int pa_frames_per_buffer = 0;
@ -196,7 +196,7 @@ int main(int argc, char ** argv)
progdefaults.openDefaults();
sound_init();
trx_start(scDevice.c_str());
trx_start();
progdefaults.initInterface();
fl_digi_main->show(argc, argv);
@ -221,7 +221,7 @@ void sound_init(void)
glob("/dev/dsp*", 0, NULL, &gbuf);
for (size_t i = 0; i < gbuf.gl_pathc; i++)
menuOSSDev->add(gbuf.gl_pathv[i]);
if (progdefaults.OSSdevice == "")
if (progdefaults.OSSdevice.length() == 0)
progdefaults.OSSdevice = gbuf.gl_pathv[0];
menuOSSDev->value(progdefaults.OSSdevice.c_str());
globfree(&gbuf);
@ -243,21 +243,33 @@ void sound_init(void)
s.insert(i, 1, '\\');
i += 2;
}
menuPADev->add(s.c_str());
if ((*idev)->maxInputChannels > 0)
menuPortInDev->add(s.c_str());
if ((*idev)->maxOutputChannels > 0)
menuPortOutDev->add(s.c_str());
}
// set the initial value in the configuration structure
if (progdefaults.PAdevice == "")
progdefaults.PAdevice = (*(SoundPort::devices().begin() + Pa_GetDefaultOutputDevice()))->name;
menuPADev->value(progdefaults.PAdevice.c_str());
btnAudioIO[1]->activate();
if (progdefaults.PortInDevice.length() == 0) {
if (progdefaults.PAdevice.length() == 0)
progdefaults.PortInDevice = (*(SoundPort::devices().begin() + Pa_GetDefaultInputDevice()))->name;
else
progdefaults.PortInDevice = progdefaults.PAdevice;
}
menuPortInDev->value(progdefaults.PortInDevice.c_str());
if (progdefaults.PortOutDevice.length() == 0) {
if (progdefaults.PAdevice.length() == 0)
progdefaults.PortOutDevice = (*(SoundPort::devices().begin() + Pa_GetDefaultOutputDevice()))->name;
else
progdefaults.PortOutDevice = progdefaults.PAdevice;
}
menuPortOutDev->value(progdefaults.PortOutDevice.c_str());
#endif
#if USE_OSS
glob("/dev/mixer*", 0, NULL, &gbuf);
for (size_t i = 0; i < gbuf.gl_pathc; i++)
for (size_t i = 0; i < gbuf.gl_pathc; i++)
menuMix->add(gbuf.gl_pathv[i]);
if (progdefaults.MXdevice == "")
if (progdefaults.MXdevice.length() == 0)
progdefaults.MXdevice = gbuf.gl_pathv[0];
globfree(&gbuf);
menuMix->value(progdefaults.MXdevice.c_str());
@ -268,15 +280,19 @@ void sound_init(void)
// set the Sound Card configuration tab to the correct initial values
#if !USE_OSS
btnAudioIO[0]->deactivate();
AudioOSS->deactivate();
btnAudioIO[SND_IDX_OSS]->deactivate();
#endif
#if !USE_PORTAUDIO
btnAudioIO[1]->deactivate();
AudioPort->deactivate();
btnAudioIO[SND_IDX_PORT]->deactivate();
#endif
#if !USE_PULSEAUDIO
btnAudioIO[2]->deactivate();
AudioPulse->deactivate();
btnAudioIO[SND_IDX_PULSE]->deactivate();
#endif
if (progdefaults.btnAudioIOis == -1 || !btnAudioIO[progdefaults.btnAudioIOis]->active()) {
if (progdefaults.btnAudioIOis == SND_IDX_UNKNOWN ||
!btnAudioIO[progdefaults.btnAudioIOis]->active()) { // or saved sound api now disabled
for (size_t i = 0; i < sizeof(btnAudioIO)/sizeof(*btnAudioIO); i++) {
if (btnAudioIO[i]->active()) {
progdefaults.btnAudioIOis = i;
@ -284,33 +300,8 @@ void sound_init(void)
}
}
}
switch (progdefaults.btnAudioIOis) {
case 0:
scDevice = progdefaults.OSSdevice;
btnAudioIO[0]->value(1);
btnAudioIO[1]->value(0);
btnAudioIO[2]->value(0);
menuOSSDev->activate();
menuPADev->deactivate();
menuSampleRate->deactivate();
break;
case 1:
scDevice = progdefaults.PAdevice;
btnAudioIO[0]->value(0);
btnAudioIO[1]->value(1);
btnAudioIO[2]->value(0);
menuOSSDev->deactivate();
menuPADev->activate();
break;
case 2:
scDevice = "localhost";
btnAudioIO[0]->value(0);
btnAudioIO[1]->value(0);
btnAudioIO[2]->value(1);
menuOSSDev->deactivate();
menuPADev->deactivate();
break;
}
update_sound_config(progdefaults.btnAudioIOis);
resetMixerControls();
}

Wyświetl plik

@ -134,10 +134,14 @@ configuration progdefaults = {
"fldigi ", // secondary text
// Sound card
-1, // int btnAudioIOis
"", // string SCdevice;
"", // string OSSdevice;
"", // string PAdevice;
"", // string PortIndevice;
"", // string PortOutDevice;
"", // string PulseServer
0, // int sample_rate;
-1, // int in_sample_rate;
-1, // int out_sample_rate;
"src-sinc-fastest", // string sample_converter;
0, // int RX_corr;
0, // int TX_corr;
@ -226,8 +230,8 @@ enum TAG { \
HAMRIGNAME, HAMRIGDEVICE, HAMRIGBAUDRATE,
PTTDEV,
SECONDARYTEXT,
AUDIOIO, SCDEVICE, OSSDEVICE, PADEVICE,
SAMPLERATE, RXCORR, TXCORR, TXOFFSET,
AUDIOIO, OSSDEVICE, PADEVICE, PORTINDEVICE, PORTOUTDEVICE, PULSESERVER,
SAMPLERATE, INSAMPLERATE, OUTSAMPLERATE, RXCORR, TXCORR, TXOFFSET,
USELEADINGZEROS, CONTESTSTART, CONTESTDIGITS,
USETIMER, MACRONUMBER, TIMEOUT,
MXDEVICE, RCVMIXER, XMTMIXER, PCMVOLUME,
@ -392,11 +396,14 @@ void configuration::writeDefaultsXML()
writeXMLstr(f, "PTTDEV", PTTdev);
writeXMLstr(f, "SECONDARYTEXT", secText);
writeXMLint(f, "AUDIOIO", btnAudioIOis);
writeXMLstr(f, "SCDEVICE", SCdevice);
writeXMLint(f, "AUDIOIO", btnAudioIOis);
writeXMLstr(f, "OSSDEVICE", OSSdevice);
writeXMLstr(f, "PADEVICE", PAdevice);
writeXMLstr(f, "PORTINDEVICE", PortInDevice);
writeXMLstr(f, "PORTOUTDEVICE", PortOutDevice);
writeXMLint(f, "SAMPLERATE", sample_rate);
writeXMLint(f, "INSAMPLERATE", in_sample_rate);
writeXMLint(f, "OUTSAMPLERATE", out_sample_rate);
writeXMLint(f, "RXCORR", RX_corr);
writeXMLint(f, "TXCORR", TX_corr);
writeXMLint(f, "TXOFFSET", TxOffset);
@ -738,18 +745,30 @@ bool configuration::readDefaultsXML()
case AUDIOIO :
btnAudioIOis = atoi(xml->getNodeData());
break;
case SCDEVICE :
SCdevice = xml->getNodeData();
break;
case OSSDEVICE :
OSSdevice = xml->getNodeData();
break;
case PADEVICE :
PAdevice = xml->getNodeData();
break;
case PORTINDEVICE :
PortInDevice = xml->getNodeData();
break;
case PORTOUTDEVICE :
PortOutDevice = xml->getNodeData();
break;
case PULSESERVER :
PulseServer = xml->getNodeData();
break;
case SAMPLERATE :
sample_rate = atoi(xml->getNodeData());
break;
case INSAMPLERATE :
in_sample_rate = atoi(xml->getNodeData());
break;
case OUTSAMPLERATE :
out_sample_rate = atoi(xml->getNodeData());
break;
case RXCORR :
RX_corr = atoi(xml->getNodeData());
break;
@ -960,10 +979,13 @@ bool configuration::readDefaultsXML()
else if (!strcmp("PTTDEV", nodeName)) tag = PTTDEV;
else if (!strcmp("SECONDARYTEXT", nodeName)) tag = SECONDARYTEXT;
else if (!strcmp("AUDIOIO", nodeName)) tag = AUDIOIO;
else if (!strcmp("SCDEVICE", nodeName)) tag = SCDEVICE;
else if (!strcmp("OSSDEVICE", nodeName)) tag = OSSDEVICE;
else if (!strcmp("PADEVICE", nodeName)) tag = PADEVICE;
else if (!strcmp("PORTINDEVICE", nodeName)) tag = PORTINDEVICE;
else if (!strcmp("PORTOUTDEVICE", nodeName)) tag = PORTOUTDEVICE;
else if (!strcmp("SAMPLERATE", nodeName)) tag = SAMPLERATE;
else if (!strcmp("INSAMPLERATE", nodeName)) tag = INSAMPLERATE;
else if (!strcmp("OUTSAMPLERATE", nodeName)) tag = OUTSAMPLERATE;
else if (!strcmp("RXCORR", nodeName)) tag = RXCORR;
else if (!strcmp("TXCORR", nodeName)) tag = TXCORR;
else if (!strcmp("TXOFFSET", nodeName)) tag = TXOFFSET;
@ -1280,26 +1302,32 @@ int configuration::openDefaults() {
btnMicIn->value(MicIn);
btnLineIn->value(LineIn);
btnAudioIO[0]->value(0);
btnAudioIO[0]->value(0);
btnAudioIO[btnAudioIOis]->value(1);
menuOSSDev->value(OSSdevice.c_str());
menuPADev->value(PAdevice.c_str());
if (btnAudioIOis == 1)
menuPADev->activate();
menuPortInDev->value(PortInDevice.c_str());
menuPortOutDev->value(PortOutDevice.c_str());
inpPulseServer->value(PulseServer.c_str());
btnMixer->value(EnableMixer);
resetMixerControls();
menuMix->value(MXdevice.c_str());
if (sample_rate > 1) {
char s[6+1];
snprintf(s, sizeof(s), "%d", sample_rate);
menuSampleRate->value(menuSampleRate->find_item(s));
char sr[6+1];
if (in_sample_rate == -1)
in_sample_rate = sample_rate;
if (in_sample_rate > 1) {
snprintf(sr, sizeof(sr), "%d", in_sample_rate);
menuInSampleRate->value(menuInSampleRate->find_item(sr));
}
else
menuSampleRate->value(sample_rate);
menuInSampleRate->value(in_sample_rate);
if (out_sample_rate == -1)
out_sample_rate = sample_rate;
if (out_sample_rate > 1) {
snprintf(sr, sizeof(sr), "%d", out_sample_rate);
menuOutSampleRate->value(menuOutSampleRate->find_item(sr));
}
else
menuOutSampleRate->value(out_sample_rate);
cntRxRateCorr->value(RX_corr);
cntTxRateCorr->value(TX_corr);

Wyświetl plik

@ -4,6 +4,8 @@
// Copyright (C) 2006
// Dave Freese, W1HKJ
// Leigh Klotz, WA5ZNU
// Copyright (C) 2008
// Stelios Bounanos, M0GLD
//
// This file is part of fldigi.
//
@ -60,11 +62,7 @@ using namespace std;
int rotoroffset = 0;
string htmlpage = "";
string xmlpage = "";
string sessionpage = "";
string host = "online.qrz.com";
string detail;
string qrzSessionKey;
string qrzalert;
string qrzerror;
@ -83,17 +81,7 @@ string qrzlatd;
string qrzlond;
string qrznotes;
const char *error[] = {
"OK", // err 0
"Host not found", // err 1
"Not an IP host!", // err 2
"No http service", // err 3
"Cannot open socket", // err 4
"Cannot Connect to server", // err 5
"Socket write error", // err 6
"Socket timeout", // err 7
"Socket select error" // err 8
};
const char* error_string;
enum QUERYTYPE { NONE, QRZCD, QRZNET, HAMCALLNET };
QUERYTYPE DB_query = NONE;
@ -104,16 +92,6 @@ enum TAG { \
ZIP, COUNTRY,LATD, LOND, GRID, \
DOB };
char rbuffer[32768];
fd_set readfds, testfds;
struct timeval timeout;
int sockfd = -1;
int result;
struct sockaddr_in address;
struct hostent *hostinfo;
struct servent *servinfo;
int qrzdummy;
Fl_Thread QRZ_thread;
bool QRZ_exit = false;
@ -123,8 +101,12 @@ static void *CALLSIGNloop(void *args);
bool parseSessionKey();
bool parse_xml();
int getSessionKey();
int QRZGetXML();
int connect_to_server(const char* node, const char* service, int* fd);
ssize_t read_from_server(int fd, const string& request, string& reply, struct timeval* timeout);
bool getSessionKey(string& sessionpage);
bool QRZGetXML(string& xmlpage);
int bearing(const char *, const char *);
void qra(const char *, double &, double &);
void QRZ_disp_result();
@ -135,16 +117,16 @@ void QRZinit(void);
void QRZclose(void);
void qthappend(string &qth, string &datum);
void QRZAlert();
int QRZLogin();
bool QRZLogin(string& sessionpage);
void QRZquery();
void parse_html();
int HAMCALLget();
void parse_html(const string& htmlpage);
bool HAMCALLget(string& htmlpage);
void HAMCALLquery();
QRZ *qCall;
bool parseSessionKey()
bool parseSessionKey(const string& sessionpage)
{
IrrXMLReader* xml = createIrrXMLReader(new IIrrXMLStringReader(sessionpage));
TAG tag=IGNORE;
@ -190,11 +172,11 @@ bool parseSessionKey()
}
}
delete xml;
return 0;
return true;
}
bool parse_xml()
bool parse_xml(const string& xmlpage)
{
IrrXMLReader* xml = createIrrXMLReader(new IIrrXMLStringReader(xmlpage));
@ -328,158 +310,158 @@ bool parse_xml()
// delete the xml parser after usage
delete xml;
return 0;
return true;
}
int getSessionKey()
// Open a stream socket, connect it to "service" running on "node", and copy it
// to *fd. Return 0 if successful, < 0 if getaddrinfo failed, or errno if there
// was some other error.
int connect_to_server(const char* node, const char* service, int* fd)
{
hostinfo = gethostbyname(host.c_str());
if(!hostinfo)
return 1;
if(hostinfo->h_addrtype != AF_INET)
return 2;
servinfo = getservbyname("http", "tcp");
if(!servinfo)
return 3;
struct addrinfo hints, *ai, *aip;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
return 4;
address.sin_family = AF_INET;
address.sin_port = servinfo->s_port;
address.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list;
memset(&hints, 0, sizeof(hints));
#ifdef AI_ADDRCONFIG
hints.ai_flags = AI_ADDRCONFIG;
#endif
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
if(result == -1) {
close(sockfd);
return 5;
}
{
detail = "GET /bin/xml?username=";
detail += progdefaults.QRZusername;
detail += ";password=";
detail += progdefaults.QRZuserpassword;
detail += ";version=";
detail += PACKAGE_NAME;
detail += "/";
detail += PACKAGE_VERSION;
detail += " HTTP/1.0\n";
detail += "Host: ";
detail += host;
detail += "\n";
detail += "Connection: close\n";
detail += "\n";
}
result = write(sockfd, detail.c_str() , detail.length());
if (result != (int)detail.length()) {
close(sockfd);
return 6;
}
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
while (1) {
testfds = readfds;
timeout.tv_sec = 5; // timeout = 5 seconds
timeout.tv_usec = 0;
result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout);
if (result == 0) {
int res;
if ((res = getaddrinfo(node, service, &hints, &ai)) < 0)
return res;
for (aip = ai; aip; aip = ai->ai_next) { // use the first one that works
if ((*fd = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1)
continue;
if (connect(*fd, aip->ai_addr, aip->ai_addrlen) == 0)
break;
}
if (result == -1) {
close(sockfd);
return 8;
}
if (FD_ISSET(sockfd, &testfds)) {
memset(rbuffer, 0, 32768);
result = read(sockfd, rbuffer, sizeof(rbuffer));
if (result <= 0) break;
sessionpage += rbuffer;
} else {
break;
}
}
close(sockfd);
return 0;
if (!aip) { // no usable address found
res = errno;
if (*fd >= 0)
close(*fd);
}
freeaddrinfo(ai);
return res;
}
int QRZGetXML()
// Write "request" to socket fd, append reply to "reply". Wait a maximum of
// "timeout" for each operation. Return the number of bytes read, or -ETIMEDOUT
// if a read or write timed out, or -errno if there was some other error.
ssize_t read_from_server(int fd, const string& request, string& reply, struct timeval* timeout)
{
hostinfo = gethostbyname(host.c_str());
if(!hostinfo)
return 1;
if(hostinfo->h_addrtype != AF_INET)
return 2;
servinfo = getservbyname("http", "tcp");
if(!servinfo)
return 3;
char rbuffer[32768];
fd_set rwset;
ssize_t res, n;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
return 4;
address.sin_family = AF_INET;
address.sin_port = servinfo->s_port;
address.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list;
// write request
n = 0;
for (;;) {
FD_ZERO(&rwset);
FD_SET(fd, &rwset);
res = select(fd + 1, 0, &rwset, 0, timeout);
if (res == -1)
return -errno;
else if (res == 0)
return -ETIMEDOUT;
result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
if(result == -1) {
close(sockfd);
return 5;
}
{
detail = "GET /bin/xml?s=";
detail += qrzSessionKey;
detail += ";callsign=";
detail += callsign;
detail += " HTTP/1.0\n";
detail += "Host: ";
detail += host;
detail += "\n";
detail += "Connection: close\n";
detail += "\n";
}
result = write(sockfd, detail.c_str() , detail.length());
if (result != (int)detail.length()) {
close(sockfd);
return 6;
}
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
while (1) {
testfds = readfds;
timeout.tv_sec = 5; // timeout = 5 seconds
timeout.tv_usec = 0;
result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout);
if (result == 0) {
res = write(fd, request.c_str() + n, request.length() - n);
if (res > 0)
n += res;
else
return -errno;
if ((size_t)n == request.length())
break;
}
// read reply
n = 0;
for (;;) {
FD_ZERO(&rwset);
FD_SET(fd, &rwset);
res = select(fd + 1, &rwset, 0, 0, timeout);
if (res == -1)
return -errno;
else if (res == 0)
return -ETIMEDOUT;
res = read(fd, rbuffer, sizeof(rbuffer));
if (res > 0) {
reply.append(rbuffer, (unsigned)res);
n += res;
}
if (result == -1) {
close(sockfd);
return 8;
}
if (FD_ISSET(sockfd, &testfds)) {
memset(rbuffer, 0, 32768);
result = read(sockfd, rbuffer, sizeof(rbuffer));
if (result <= 0) break;
xmlpage += rbuffer;
} else {
else {
if (res < 0)
return -errno;
break;
}
}
return n;
}
bool getSessionKey(string& sessionpage)
{
int r, sockfd;
if ((r = connect_to_server(host.c_str(), "http", &sockfd)) != 0) {
error_string = r > 0 ? strerror(r) : gai_strerror(r);
return false;
}
string detail;
detail = "GET /bin/xml?username=";
detail += progdefaults.QRZusername;
detail += ";password=";
detail += progdefaults.QRZuserpassword;
detail += ";version=";
detail += PACKAGE_NAME;
detail += "/";
detail += PACKAGE_VERSION;
detail += " HTTP/1.0\n";
detail += "Host: ";
detail += host;
detail += "\n";
detail += "Connection: close\n";
detail += "\n";
struct timeval timeout = { 5, 0 }; // timeout = 5 seconds
ssize_t nread = read_from_server(sockfd, detail, sessionpage, &timeout);
close(sockfd);
return 0;
if (nread < 0 && nread != -ETIMEDOUT)
error_string = strerror(-nread);
// for some strange reason we return successfully even if we time out
return nread == -ETIMEDOUT || nread > 0;
}
bool QRZGetXML(string& xmlpage)
{
int r, sockfd;
if ((r = connect_to_server(host.c_str(), "http", &sockfd)) != 0) {
error_string = r > 0 ? strerror(r) : gai_strerror(r);
return false;
}
string detail;
detail = "GET /bin/xml?s=";
detail += qrzSessionKey;
detail += ";callsign=";
detail += callsign;
detail += " HTTP/1.0\n";
detail += "Host: ";
detail += host;
detail += "\n";
detail += "Connection: close\n";
detail += "\n";
struct timeval timeout = { 5, 0 }; // timeout = 5 seconds
ssize_t nread = read_from_server(sockfd, detail, xmlpage, &timeout);
close(sockfd);
if (nread < 0)
error_string = strerror(-nread);
return nread > 0;
}
int bearing(const char *myqra, const char *dxqra) {
@ -528,14 +510,14 @@ void QRZ_disp_result()
FL_LOCK();
{
if (qrzfname.length() > 0) {
int spacePos = qrzfname.find(" ");
string::size_type spacePos = qrzfname.find(" ");
// if fname is "ABC" then display "ABC"
// or if fname is "X Y" then display "X Y"
if (spacePos ==-1 || (spacePos == 1)) {
if (spacePos == string::npos || (spacePos == 1)) {
inpName->value(qrzfname.c_str());
}
// if fname is "ABC Y" then display "ABC"
else if (spacePos == ((int)qrzfname.length())-2) {
else if (spacePos == qrzfname.length() - 2) {
string fname="";
fname.assign(qrzfname, 0, spacePos);
inpName->value(fname.c_str());
@ -577,7 +559,6 @@ void QRZ_COM_query()
return;
}
xmlpage = "";
DB_query = QRZNET;
FL_LOCK();
inpNotes->value(" *** Request sent to qrz.com ***");
@ -591,10 +572,9 @@ void HAMCALL_COM_query()
if (!QRZ_enabled)
return;
}
htmlpage = "";
DB_query = HAMCALLNET;
FL_LOCK();
inpNotes->value(" *** Request sent to www.hamcomm.net ***");
inpNotes->value(" *** Request sent to www.hamcall.net ***");
FL_UNLOCK();
}
@ -673,33 +653,36 @@ void QRZAlert()
}
}
int QRZLogin() {
int err=0;
bool QRZLogin(string& sessionpage) {
bool ok = true;
if (qrzSessionKey.empty()) {
err = getSessionKey();
if (!err) err = parseSessionKey();
ok = getSessionKey(sessionpage);
if (ok) ok = parseSessionKey(sessionpage);
}
if (! err) {
if (!ok) {
QRZAlert();
}
return err;
return ok;
}
void QRZquery()
{
int err=0;
bool ok = true;
string qrzpage;
if (qrzSessionKey.empty())
err = QRZLogin();
if (!err)
err = QRZGetXML();
if (!err) {
ok = QRZLogin(qrzpage);
if (ok)
ok = QRZGetXML(qrzpage);
if (ok) {
if (qrzSessionKey.empty())
err = QRZLogin();
if (!err)
err = QRZGetXML();
ok = QRZLogin(qrzpage);
if (ok)
ok = QRZGetXML(qrzpage);
}
if (!err) {
parse_xml();
if (ok) {
parse_xml(qrzpage);
if (!qrzalert.empty()) {
FL_LOCK();
inpNotes->value(qrzalert.c_str());
@ -719,9 +702,9 @@ void QRZquery()
QRZ_disp_result();
}
}
if (err) {
if (!ok) {
FL_LOCK();
inpNotes->value(error[err]);
inpNotes->value(error_string);
FL_UNLOCK();
}
}
@ -736,7 +719,7 @@ void QRZquery()
#define HAMCALL_GRID 202
#define HAMCALL_DOB 194
void parse_html()
void parse_html(const string& htmlpage)
{
size_t p;
qrzborn="";
@ -776,85 +759,44 @@ void parse_html()
}
}
int HAMCALLget()
bool HAMCALLget(string& htmlpage)
{
int r, sockfd;
if ((r = connect_to_server(HAMCALL_HOST, "http", &sockfd)) != 0) {
error_string = r > 0 ? strerror(r) : gai_strerror(r);
return false;
}
string url_detail;
int len;
url_detail = "GET /call?username=";
url_detail = "GET /call?username=";
url_detail += progdefaults.QRZusername;
url_detail += "&password=";
url_detail += progdefaults.QRZuserpassword;
url_detail += "&rawlookup=1&callsign=";
url_detail += callsign;
url_detail += "&program=WA5ZNU/Testing/0.0+\r\n";
url_detail += "&program=fldigi-";
url_detail += VERSION;
url_detail += "\r\n";
hostinfo = gethostbyname(HAMCALL_HOST);
if(!hostinfo)
return 1;
if(hostinfo->h_addrtype != AF_INET)
return 2;
servinfo = getservbyname("http", "tcp");
if(!servinfo)
return 3;
struct timeval timeout = { 10, 0 }; // timeout = 10 seconds
ssize_t nread = read_from_server(sockfd, url_detail, htmlpage, &timeout);
close(sockfd);
if (nread < 0)
error_string = strerror(-nread);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
return 4;
address.sin_family = AF_INET;
address.sin_port = servinfo->s_port;
address.sin_addr = *(struct in_addr *)*hostinfo->h_addr_list;
result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
if(result == -1) {
close(sockfd);
return 5;
}
len = url_detail.length();
result = write(sockfd, url_detail.c_str() , len);
if (result != len) {
close(sockfd);
return 6;
}
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
testfds = readfds;
timeout.tv_sec = 15; // timeout = 10 seconds
timeout.tv_usec = 0;
result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout);
if (result == 0) {
close(sockfd);
return 7;
}
if (result == -1) {
close(sockfd);
return 8;
}
if (FD_ISSET(sockfd, &testfds)) {
memset(rbuffer, 0, 32768);
result = read(sockfd, rbuffer, sizeof(rbuffer));
if (result && result < 32768)
htmlpage += rbuffer;
}
close(sockfd);
return 0;
return nread > 0;
}
void HAMCALLquery()
{
int err;
if ((err = HAMCALLget()) == 0) {
parse_html();
string htmlpage;
if (HAMCALLget(htmlpage)) {
parse_html(htmlpage);
QRZ_disp_result();
} else {
FL_LOCK();
inpNotes->value(error[err]);
inpNotes->value(error_string);
FL_UNLOCK();
}
}

Wyświetl plik

@ -678,7 +678,7 @@ void SoundPort::initialize(void)
throw SndPortException(err);
pa_init = true;
PaDeviceIndex ndev = Pa_GetDeviceCount();
PaDeviceIndex ndev;
if ((ndev = Pa_GetDeviceCount()) < 0)
throw SndPortException(ndev);
if (ndev == 0)
@ -700,10 +700,15 @@ const std::vector<const PaDeviceInfo*>& SoundPort::devices(void)
return devs;
}
SoundPort::SoundPort(const char *dev)
: device(dev), stream(0), frames_per_buffer(paFramesPerBufferUnspecified),
req_sample_rate(0), dev_sample_rate(0), fbuf(0)
SoundPort::SoundPort(const char *in_dev, const char *out_dev)
: req_sample_rate(0), fbuf(0)
{
device[STREAM_IN] = in_dev;
device[STREAM_OUT] = out_dev;
stream[STREAM_IN] = stream[STREAM_OUT] = 0;
frames_per_buffer[STREAM_IN] = frames_per_buffer[STREAM_OUT] = paFramesPerBufferUnspecified;
dev_sample_rate[STREAM_IN] = dev_sample_rate[STREAM_OUT] = 0;
try {
rx_src_data = new SRC_DATA;
tx_src_data = new SRC_DATA;
@ -741,50 +746,61 @@ int SoundPort::Open(int mode, int freq)
// Try to keep the stream open if we are using jack, or if we
// are in full duplex mode and the sample rate has not changed.
if (stream_active()) {
if (Pa_GetHostApiInfo((*idev)->hostApi)->type == paJACK) {
if (stream_active(STREAM_IN) && stream_active(STREAM_OUT)) {
if (Pa_GetHostApiInfo((*idev[STREAM_IN])->hostApi)->type == paJACK ||
Pa_GetHostApiInfo((*idev[STREAM_OUT])->hostApi)->type == paJACK) {
// If we have a new sample rate, we must reset the src data.
if (old_sample_rate != freq)
src_data_reset(1 << O_RDONLY | 1 << O_WRONLY);
return 0;
}
else if (full_duplex_device(*idev) && old_sample_rate == freq)
else if ( (idev[STREAM_IN] != idev[STREAM_OUT] ||
full_duplex_device(*idev[STREAM_IN])) &&
old_sample_rate == freq)
return 0;
}
Close();
init_stream();
init_stream(STREAM_IN);
#ifndef NDEBUG
if (dev_sample_rate != req_sample_rate)
cerr << "PA_debug: resampling " << dev_sample_rate
if (dev_sample_rate[STREAM_IN] != req_sample_rate)
cerr << "PA_debug: input: resampling " << dev_sample_rate[STREAM_IN]
<< " <-> " << req_sample_rate << endl;
#endif
init_stream(STREAM_OUT);
#ifndef NDEBUG
if (dev_sample_rate[STREAM_OUT] != req_sample_rate)
cerr << "PA_debug: output: resampling " << dev_sample_rate[STREAM_OUT]
<< " <-> " << req_sample_rate << endl;
#endif
mode = full_duplex() ? 1 << O_RDONLY | 1 << O_WRONLY : 1 << mode;
if (!(mode & 1 << O_WRONLY))
stream_params[STREAM_OUT] = NULL;
if (!(mode & 1 << O_RDONLY))
stream_params[STREAM_IN] = NULL;
src_data_reset(mode);
start_stream();
if (mode & 1 << O_RDONLY)
start_stream(STREAM_IN);
if (mode & 1 << O_WRONLY)
start_stream(STREAM_OUT);
return 0;
}
void SoundPort::Close(void)
{
if (!stream_active())
return;
int err;
for (int i = 0; i < 2; i++) {
if (!stream_active(i))
return;
int err;
if ((err = Pa_StopStream(stream[i])) != paNoError)
pa_perror(err, "Pa_StopStream");
if ((err = Pa_CloseStream(stream[i])) != paNoError)
pa_perror(err, "Pa_CloseStream");
if ((err = Pa_StopStream(stream)) != paNoError)
pa_perror(err, "Pa_StopStream");
if ((err = Pa_CloseStream(stream)) != paNoError)
pa_perror(err, "Pa_CloseStream");
stream = 0;
stream[i] = 0;
}
}
size_t SoundPort::Read(double *buf, size_t count)
@ -793,13 +809,13 @@ size_t SoundPort::Read(double *buf, size_t count)
int err;
static int retries = 0;
if ((err = Pa_ReadStream(stream, fbuf, ncount)) != paNoError) {
if ((err = Pa_ReadStream(stream[STREAM_IN], fbuf, ncount)) != paNoError) {
pa_perror(err, "Pa_ReadStream");
switch (err) {
case paInputOverflowed:
return adjust_stream() ? Read(buf, count) : 0;
return 0;
case paUnanticipatedHostError:
if (Pa_GetHostApiInfo((*idev)->hostApi)->type == paOSS && retries++ < 8) {
if (Pa_GetHostApiInfo((*idev[STREAM_IN])->hostApi)->type == paOSS && retries++ < 8) {
cerr << "Retrying read\n";
return Read(buf, count);
}
@ -825,7 +841,7 @@ size_t SoundPort::Read(double *buf, size_t count)
}
float *rbuf = fbuf;
if (req_sample_rate != dev_sample_rate || progdefaults.RX_corr != 0) {
if (req_sample_rate != dev_sample_rate[STREAM_IN] || progdefaults.RX_corr != 0) {
resample(1 << O_RDONLY, rbuf, ncount, count);
rbuf = rx_src_data->data_out;
count = rx_src_data->output_frames_gen;
@ -846,21 +862,21 @@ size_t SoundPort::Write(double *buf, size_t count)
fbuf[2*i] = fbuf[2*i + 1] = buf[i];
float *wbuf = fbuf;
if (req_sample_rate != dev_sample_rate || progdefaults.TX_corr != 0) {
if (req_sample_rate != dev_sample_rate[STREAM_OUT] || progdefaults.TX_corr != 0) {
resample(1 << O_WRONLY, wbuf, count);
wbuf = tx_src_data->data_out;
count = tx_src_data->output_frames_gen;
}
int err;
static int retries = 0;
if ((err = Pa_WriteStream(stream, wbuf, count)) != paNoError) {
static unsigned retries = 0;
if ((err = Pa_WriteStream(stream[STREAM_OUT], wbuf, count)) != paNoError) {
pa_perror(err, "Pa_WriteStream");
switch (err) {
case paOutputUnderflowed:
return adjust_stream() ? Write(buf, count) : 0;
return 0;
case paUnanticipatedHostError:
if (Pa_GetHostApiInfo((*idev)->hostApi)->type == paOSS && retries++ < 8) {
if (Pa_GetHostApiInfo((*idev[STREAM_OUT])->hostApi)->type == paOSS && retries++ < 8) {
cerr << "Retrying write\n";
return Write(buf, count);
}
@ -887,26 +903,28 @@ size_t SoundPort::Write_stereo(double *bufleft, double *bufright, size_t count)
}
float *wbuf = fbuf;
if (req_sample_rate != dev_sample_rate || progdefaults.TX_corr != 0) {
if (req_sample_rate != dev_sample_rate[STREAM_OUT] || progdefaults.TX_corr != 0) {
resample(1 << O_WRONLY, wbuf, count);
wbuf = tx_src_data->data_out;
count = tx_src_data->output_frames_gen;
}
int err;
static int retries = 0;
static unsigned retries = 0;
if ((err = Pa_WriteStream(stream, wbuf, count)) != paNoError) {
pa_perror(err, "Pa_WriteStream");
switch (err) {
case paOutputUnderflowed:
return adjust_stream() ? Write_stereo(bufleft, bufright, count) : 0;
return 0;
case paUnanticipatedHostError:
if (Pa_GetHostApiInfo((*idev)->hostApi)->type == paOSS && retries++ < 8) {
if (Pa_GetHostApiInfo((*idev[STREAM_OUT])->hostApi)->type == paOSS && retries++ < 8) {
cerr << "Retrying write\n";
return Write_stereo(bufleft, bufright, count);
}
else
else {
cerr << "Giving up\n";
retries = 0;
}
// fall through
default:
throw SndPortException(err);
@ -922,8 +940,10 @@ size_t SoundPort::Write_stereo(double *bufleft, double *bufright, size_t count)
bool SoundPort::full_duplex(void)
{
extern bool pa_allow_full_duplex;
return (pa_allow_full_duplex && full_duplex_device(*idev)) ||
Pa_GetHostApiInfo((*idev)->hostApi)->type == paJACK;
return (pa_allow_full_duplex && full_duplex_device(*idev[STREAM_IN])) ||
idev[STREAM_IN] != idev[STREAM_OUT] ||
(Pa_GetHostApiInfo((*idev[STREAM_IN])->hostApi)->type == paJACK ||
Pa_GetHostApiInfo((*idev[STREAM_OUT])->hostApi)->type == paJACK);
}
void SoundPort::src_data_reset(int mode)
@ -935,7 +955,7 @@ void SoundPort::src_data_reset(int mode)
rx_src_state = src_new(sample_converter, 2, &err);
if (!rx_src_state)
throw SndException(src_strerror(err));
rx_src_data->src_ratio = req_sample_rate / (dev_sample_rate * (1.0 + rxppm / 1e6));
rx_src_data->src_ratio = req_sample_rate / (dev_sample_rate[STREAM_IN] * (1.0 + rxppm / 1e6));
}
if (mode & 1 << O_WRONLY) {
if (tx_src_state)
@ -943,7 +963,7 @@ void SoundPort::src_data_reset(int mode)
tx_src_state = src_new(sample_converter, 2, &err);
if (!tx_src_state)
throw SndException(src_strerror(err));
tx_src_data->src_ratio = dev_sample_rate * (1.0 + txppm / 1e6) / req_sample_rate;
tx_src_data->src_ratio = dev_sample_rate[STREAM_OUT] * (1.0 + txppm / 1e6) / req_sample_rate;
}
}
@ -955,7 +975,7 @@ void SoundPort::resample(int mode, float *buf, size_t count, size_t max)
if (rxppm != progdefaults.RX_corr) {
rxppm = progdefaults.RX_corr;
rx_src_data->src_ratio = req_sample_rate
/ dev_sample_rate
/ dev_sample_rate[STREAM_IN]
* (1.0 + rxppm / 1e6);
src_set_ratio(rx_src_state, rx_src_data->src_ratio);
}
@ -972,7 +992,7 @@ void SoundPort::resample(int mode, float *buf, size_t count, size_t max)
else if (mode & 1 << O_WRONLY) {
if (txppm != progdefaults.TX_corr) {
txppm = progdefaults.TX_corr;
tx_src_data->src_ratio = dev_sample_rate
tx_src_data->src_ratio = dev_sample_rate[STREAM_OUT]
* (1.0 + txppm / 1e6)
/ req_sample_rate;
src_set_ratio(tx_src_state, tx_src_data->src_ratio);
@ -989,97 +1009,98 @@ void SoundPort::resample(int mode, float *buf, size_t count, size_t max)
}
}
void SoundPort::init_stream(void)
void SoundPort::init_stream(unsigned dir)
{
#ifndef NDEBUG
cerr << "PA_debug: looking for \"" << device << "\"\n";
cerr << "PA_debug: looking for \"" << device[dir] << "\"\n";
#endif
for (idev = devs.begin(); idev != devs.end(); ++idev)
if (device == (*idev)->name)
for (idev[dir] = devs.begin(); idev[dir] != devs.end(); ++idev[dir])
if (device[dir] == (*idev[dir])->name)
break;
if (idev == devs.end()) {
cerr << "PA_debug: could not find device \"" << device << "\"\n";
idev = devs.begin() + Pa_GetDefaultOutputDevice();
if (idev[dir] == devs.end()) {
cerr << "PA_debug: could not find device \"" << device[dir] << "\"\n";
idev[dir] = devs.begin() + (dir == STREAM_IN ? Pa_GetDefaultInputDevice() : Pa_GetDefaultOutputDevice());
}
PaDeviceIndex idx = idev - devs.begin();
PaDeviceIndex idx = idev[dir] - devs.begin();
#ifndef NDEBUG
cerr << "PA_debug: using device:"
cerr << "PA_debug: using " << (dir == STREAM_IN ? "input" : "output") << " device:"
<< "\n index: " << idx
<< "\n name: " << (*idev)->name
<< "\n hostAPI: " << Pa_GetHostApiInfo((*idev)->hostApi)->name
<< "\n maxInputChannels: " << (*idev)->maxInputChannels
<< "\n maxOutputChannels: " << (*idev)->maxOutputChannels
<< "\n defaultLowInputLatency: " << (*idev)->defaultLowInputLatency
<< "\n defaultHighInputLatency: " << (*idev)->defaultHighInputLatency
<< "\n defaultLowOutputLatency: " << (*idev)->defaultLowOutputLatency
<< "\n defaultHighOutputLatency: " << (*idev)->defaultHighOutputLatency
<< "\n defaultSampleRate: " << (*idev)->defaultSampleRate
<< "\n name: " << (*idev[dir])->name
<< "\n hostAPI: " << Pa_GetHostApiInfo((*idev[dir])->hostApi)->name
<< "\n maxInputChannels: " << (*idev[dir])->maxInputChannels
<< "\n maxOutputChannels: " << (*idev[dir])->maxOutputChannels
<< "\n defaultLowInputLatency: " << (*idev[dir])->defaultLowInputLatency
<< "\n defaultHighInputLatency: " << (*idev[dir])->defaultHighInputLatency
<< "\n defaultLowOutputLatency: " << (*idev[dir])->defaultLowOutputLatency
<< "\n defaultHighOutputLatency: " << (*idev[dir])->defaultHighOutputLatency
<< "\n defaultSampleRate: " << (*idev[dir])->defaultSampleRate
<< boolalpha
<< "\n isInputOnlyDevice: " << ((*idev)->maxOutputChannels == 0)
<< "\n isOutputOnlyDevice: " << ((*idev)->maxInputChannels == 0)
<< "\n isFullDuplexDevice: " << full_duplex_device(*idev)
<< "\n isInputOnlyDevice: " << ((*idev[dir])->maxOutputChannels == 0)
<< "\n isOutputOnlyDevice: " << ((*idev[dir])->maxInputChannels == 0)
<< "\n isFullDuplexDevice: " << full_duplex_device(*idev[dir])
<< "\n isSystemDefaultInputDevice: " << (idx == Pa_GetDefaultInputDevice())
<< "\n isSystemDefaultOutputDevice: " << (idx == Pa_GetDefaultOutputDevice())
<< "\n isHostApiDefaultInputDevice: " << (idx == Pa_GetHostApiInfo((*idev)->hostApi)->defaultInputDevice)
<< "\n isHostApiDefaultOutputDevice: " << (idx == Pa_GetHostApiInfo((*idev)->hostApi)->defaultOutputDevice)
<< "\n isHostApiDefaultInputDevice: " << (idx == Pa_GetHostApiInfo((*idev[dir])->hostApi)->defaultInputDevice)
<< "\n isHostApiDefaultOutputDevice: " << (idx == Pa_GetHostApiInfo((*idev[dir])->hostApi)->defaultOutputDevice)
<< "\n\n";
#endif
// we are unlikely to have an output-only device
if ((*idev)->maxInputChannels == 0)
throw SndPortException(EBUSY);
if ((dir == STREAM_IN && (*idev[dir])->maxInputChannels == 0) ||
(dir == STREAM_OUT && (*idev[dir])->maxOutputChannels == 0))
throw SndException(EBUSY);
in_params.device = idx;
in_params.channelCount = 2;
in_params.sampleFormat = paFloat32;
in_params.suggestedLatency = (*idev)->defaultHighInputLatency;
in_params.hostApiSpecificStreamInfo = NULL;
stream_params[STREAM_IN] = &in_params;
if (dir == STREAM_IN) {
stream_params[STREAM_IN].device = idx;
stream_params[STREAM_IN].channelCount = 2;
stream_params[STREAM_IN].sampleFormat = paFloat32;
stream_params[STREAM_IN].suggestedLatency = (*idev[dir])->defaultHighInputLatency;
stream_params[STREAM_IN].hostApiSpecificStreamInfo = NULL;
}
else {
stream_params[STREAM_OUT].device = idx;
stream_params[STREAM_OUT].channelCount = 2;
stream_params[STREAM_OUT].sampleFormat = paFloat32;
stream_params[STREAM_OUT].suggestedLatency = (*idev[dir])->defaultHighOutputLatency;
stream_params[STREAM_OUT].hostApiSpecificStreamInfo = NULL;
}
out_params.device = idx;
out_params.channelCount = 2;
out_params.sampleFormat = paFloat32;
out_params.suggestedLatency = (*idev)->defaultHighOutputLatency;
out_params.hostApiSpecificStreamInfo = NULL;
stream_params[STREAM_OUT] = &out_params;
dev_sample_rate[dir] = find_srate(dir);
dev_sample_rate = find_srate();
max_frames_per_buffer = ceil2(MIN(SND_BUF_LEN, (unsigned)(SCBLOCKSIZE *
dev_sample_rate / req_sample_rate)));
#ifndef NDEBUG
cerr << "PA_debug: max_frames_per_buffer = " << max_frames_per_buffer << endl;
#endif
extern int pa_frames_per_buffer;
if (pa_frames_per_buffer)
frames_per_buffer = pa_frames_per_buffer;
frames_per_buffer[dir] = pa_frames_per_buffer;
}
void SoundPort::start_stream(void)
void SoundPort::start_stream(unsigned dir)
{
int err;
err = Pa_OpenStream(&stream, stream_params[STREAM_IN], stream_params[STREAM_OUT],
dev_sample_rate, frames_per_buffer, paNoFlag, NULL, NULL);
if (err != paNoError)
throw SndPortException(err);
if ((err = Pa_StartStream(stream)) != paNoError) {
Close();
throw SndPortException(err);
}
if (dir == STREAM_IN)
err = Pa_OpenStream(&stream[STREAM_IN], &stream_params[STREAM_IN], NULL,
dev_sample_rate[STREAM_IN], frames_per_buffer[STREAM_IN],
paNoFlag, NULL, NULL);
else
err = Pa_OpenStream(&stream[STREAM_OUT], NULL, &stream_params[STREAM_OUT],
dev_sample_rate[STREAM_OUT], frames_per_buffer[STREAM_OUT],
paNoFlag, NULL, NULL);
if (err != paNoError)
throw SndPortException(err);
if ((err = Pa_StartStream(stream[dir])) != paNoError) {
Close();
throw SndPortException(err);
}
}
bool SoundPort::stream_active(void)
bool SoundPort::stream_active(unsigned dir)
{
if (!stream)
if (!stream[dir])
return false;
int err;
if ((err = Pa_IsStreamActive(stream)) < 0)
if ((err = Pa_IsStreamActive(stream[dir])) < 0)
throw SndPortException(err);
return err == 1;
}
@ -1088,50 +1109,30 @@ bool SoundPort::full_duplex_device(const PaDeviceInfo* dev)
return dev->maxInputChannels > 0 && dev->maxOutputChannels > 0;
}
bool SoundPort::adjust_stream(void)
{
if (frames_per_buffer == max_frames_per_buffer)
return false;
if (frames_per_buffer != paFramesPerBufferUnspecified)
frames_per_buffer *= 2;
else
frames_per_buffer = SCBLOCKSIZE;
if (!powerof2(frames_per_buffer))
frames_per_buffer = ceil2(frames_per_buffer);
frames_per_buffer = MIN(max_frames_per_buffer, frames_per_buffer);
cerr << "PA_debug: adjusting frames_per_buffer to "
<< frames_per_buffer << endl;
Close();
start_stream();
return true;
}
// Determine the sample rate that we will use. We try the modem's rate
// first and fall back to the device's default rate. If there is a user
// setting we just return that without making any checks.
double SoundPort::find_srate(void)
double SoundPort::find_srate(unsigned dir)
{
switch (progdefaults.sample_rate) {
case 0:
int sr = (dir == STREAM_IN ? progdefaults.in_sample_rate : progdefaults.out_sample_rate);
switch (sr) {
case -1: case 0:
break;
case 1:
return (*idev)->defaultSampleRate;
return (*idev[dir])->defaultSampleRate;
default:
return progdefaults.sample_rate;
return sr;
}
double srates[] = { req_sample_rate, (*idev)->defaultSampleRate };
double srates[] = { req_sample_rate, (*idev[dir])->defaultSampleRate };
int err;
for (size_t i = 0; i < sizeof(srates)/sizeof(srates[0]); i++) {
#ifndef NDEBUG
cerr << "PA_debug: trying " << srates[i] << " Hz" << endl;
#endif
if ((err = Pa_IsFormatSupported(&in_params, &out_params, srates[i])) == paFormatIsSupported)
if ((err = Pa_IsFormatSupported((dir == STREAM_IN ? &stream_params[STREAM_IN] : NULL),
(dir == STREAM_OUT ? &stream_params[STREAM_OUT] : NULL),
srates[i])) == paFormatIsSupported)
return srates[i];
#ifndef NDEBUG
else
@ -1153,7 +1154,8 @@ void SoundPort::pa_perror(int err, const char* str)
if (i < 0) { // PA failed without setting its "last host error" info. Sigh...
cerr << "Host API error info not available\n";
if (Pa_GetHostApiInfo((*idev)->hostApi)->type == paOSS && errno)
if ((Pa_GetHostApiInfo((*idev[STREAM_IN])->hostApi)->type == paOSS ||
Pa_GetHostApiInfo((*idev[STREAM_OUT])->hostApi)->type == paOSS) && errno)
cerr << "Possible OSS error " << errno << ": "
<< strerror(errno) << '\n';
}
@ -1169,8 +1171,10 @@ void SoundPort::pa_perror(int err, const char* str)
#if USE_PULSEAUDIO
SoundPulse::SoundPulse(const char *dev)
: dev_sample_rate(48000), in_stream(0), out_stream(0), fbuf(0)
: fbuf(0)
{
stream[0] = stream[1] = 0;
try {
rx_src_data = new SRC_DATA;
tx_src_data = new SRC_DATA;
@ -1200,9 +1204,14 @@ SoundPulse::~SoundPulse()
int SoundPulse::Open(int mode, int freq)
{
int old_sample_rate = sample_frequency;
sample_frequency = freq;
if (in_stream && out_stream) {
dev_sample_rate[0] = (progdefaults.in_sample_rate > 1 ?
progdefaults.in_sample_rate : 48000);
dev_sample_rate[1] = (progdefaults.out_sample_rate > 1 ?
progdefaults.out_sample_rate : 48000);
sample_frequency = freq;
if (stream[0] && stream[1]) {
if (sample_frequency != old_sample_rate) {
src_data_reset(1 << O_RDONLY | 1 << O_WRONLY);
return 0;
@ -1210,25 +1219,30 @@ int SoundPulse::Open(int mode, int freq)
}
else
Close();
stream_params.format = PA_SAMPLE_FLOAT32LE;
stream_params.channels = 2;
stream_params.rate = dev_sample_rate;
const char* server = (progdefaults.PulseServer.length() ?
progdefaults.PulseServer.c_str() : NULL);
char sname[32];
int err;
stream_params.format = PA_SAMPLE_FLOAT32LE;
stream_params.channels = 2;
stream_params.rate = dev_sample_rate[0];
snprintf(sname, sizeof(sname), "capture (%u)", getpid());
if (!in_stream) {
in_stream = pa_simple_new(NULL, PACKAGE_NAME, PA_STREAM_RECORD, NULL,
if (!stream[0]) {
stream[0] = pa_simple_new(server, PACKAGE_NAME, PA_STREAM_RECORD, NULL,
sname, &stream_params, NULL, NULL, &err);
if (!in_stream)
if (!stream[0])
throw SndPulseException(err);
}
stream_params.rate = dev_sample_rate[1];
snprintf(sname, sizeof(sname), "playback (%u)", getpid());
if (!out_stream) {
out_stream = pa_simple_new(NULL, PACKAGE_NAME, PA_STREAM_PLAYBACK, NULL,
if (!stream[1]) {
stream[1] = pa_simple_new(server, PACKAGE_NAME, PA_STREAM_PLAYBACK, NULL,
sname, &stream_params, NULL, NULL, &err);
if (!out_stream)
if (!stream[1])
throw SndPulseException(err);
}
@ -1240,19 +1254,19 @@ int SoundPulse::Open(int mode, int freq)
void SoundPulse::Close(void)
{
int err = PA_OK;
if (in_stream) {
pa_simple_drain(in_stream, &err);
if (stream[0]) {
pa_simple_drain(stream[0], &err);
if (err != PA_OK)
cerr << pa_strerror(err) << '\n';
pa_simple_free(in_stream);
in_stream = 0;
pa_simple_free(stream[0]);
stream[0] = 0;
}
if (out_stream) {
pa_simple_drain(out_stream, &err);
if (stream[1]) {
pa_simple_drain(stream[1], &err);
if (err != PA_OK)
cerr << pa_strerror(err) << '\n';
pa_simple_free(out_stream);
out_stream = 0;
pa_simple_free(stream[1]);
stream[1] = 0;
}
}
@ -1265,14 +1279,14 @@ size_t SoundPulse::Write(double* buf, size_t count)
fbuf[2*i] = fbuf[2*i + 1] = buf[i];
float *wbuf = fbuf;
if (sample_frequency != dev_sample_rate || progdefaults.TX_corr != 0) {
if (sample_frequency != dev_sample_rate[1] || progdefaults.TX_corr != 0) {
resample(1 << O_WRONLY, wbuf, count);
wbuf = tx_src_data->data_out;
count = tx_src_data->output_frames_gen;
}
int err;
if (pa_simple_write(out_stream, wbuf, count * sizeof(double), &err) == -1)
if (pa_simple_write(stream[1], wbuf, count * sizeof(double), &err) == -1)
throw SndPulseException(err);
return count;
@ -1289,14 +1303,14 @@ size_t SoundPulse::Write_stereo(double* bufleft, double* bufright, size_t count)
}
float *wbuf = fbuf;
if (sample_frequency != dev_sample_rate || progdefaults.TX_corr != 0) {
if (sample_frequency != dev_sample_rate[1] || progdefaults.TX_corr != 0) {
resample(1 << O_WRONLY, wbuf, count);
wbuf = tx_src_data->data_out;
count = tx_src_data->output_frames_gen;
}
int err;
if (pa_simple_write(out_stream, wbuf, count * sizeof(double), &err) == -1)
if (pa_simple_write(stream[1], wbuf, count * sizeof(double), &err) == -1)
throw SndPulseException(err);
return count;
@ -1307,7 +1321,7 @@ size_t SoundPulse::Read(double *buf, size_t count)
size_t ncount = (int)MIN(SND_BUF_LEN, floor(count / rx_src_data->src_ratio));
int err;
if (pa_simple_read(in_stream, fbuf, sizeof(double) * ncount, &err) == -1)
if (pa_simple_read(stream[0], fbuf, sizeof(double) * ncount, &err) == -1)
throw SndPulseException(err);
if (capture)
@ -1323,7 +1337,7 @@ size_t SoundPulse::Read(double *buf, size_t count)
}
float *rbuf = fbuf;
if (sample_frequency != dev_sample_rate || progdefaults.RX_corr != 0) {
if (sample_frequency != dev_sample_rate[0] || progdefaults.RX_corr != 0) {
resample(1 << O_RDONLY, rbuf, ncount, count);
rbuf = rx_src_data->data_out;
count = rx_src_data->output_frames_gen;
@ -1344,7 +1358,7 @@ void SoundPulse::src_data_reset(int mode)
rx_src_state = src_new(sample_converter, stream_params.channels, &err);
if (!rx_src_state)
throw SndException(src_strerror(err));
rx_src_data->src_ratio = sample_frequency / (dev_sample_rate * (1.0 + rxppm / 1e6));
rx_src_data->src_ratio = sample_frequency / (dev_sample_rate[0] * (1.0 + rxppm / 1e6));
}
if (mode & 1 << O_WRONLY) {
if (tx_src_state)
@ -1352,7 +1366,7 @@ void SoundPulse::src_data_reset(int mode)
tx_src_state = src_new(sample_converter, stream_params.channels, &err);
if (!tx_src_state)
throw SndException(src_strerror(err));
tx_src_data->src_ratio = dev_sample_rate * (1.0 + txppm / 1e6) / sample_frequency;
tx_src_data->src_ratio = dev_sample_rate[1] * (1.0 + txppm / 1e6) / sample_frequency;
}
}
@ -1364,7 +1378,7 @@ void SoundPulse::resample(int mode, float *buf, size_t count, size_t max)
if (rxppm != progdefaults.RX_corr) {
rxppm = progdefaults.RX_corr;
rx_src_data->src_ratio = sample_frequency
/ dev_sample_rate
/ dev_sample_rate[0]
* (1.0 + rxppm / 1e6);
src_set_ratio(rx_src_state, rx_src_data->src_ratio);
}
@ -1381,7 +1395,7 @@ void SoundPulse::resample(int mode, float *buf, size_t count, size_t max)
else if (mode & 1 << O_WRONLY) {
if (txppm != progdefaults.TX_corr) {
txppm = progdefaults.TX_corr;
tx_src_data->src_ratio = dev_sample_rate
tx_src_data->src_ratio = dev_sample_rate[1]
* (1.0 + txppm / 1e6)
/ sample_frequency;
src_set_ratio(tx_src_state, tx_src_data->src_ratio);
@ -1398,5 +1412,45 @@ void SoundPulse::resample(int mode, float *buf, size_t count, size_t max)
}
}
#endif // USE_PULSEAUDIO
size_t SoundNull::Write(double* buf, size_t count)
{
if (generate)
writeGenerate(buf, count);
usleep((useconds_t)ceil((1e6 * count) / sample_frequency));
return count;
}
size_t SoundNull::Write_stereo(double* bufleft, double* bufright, size_t count)
{
if (generate)
writeGenerate(bufleft, count);
usleep((useconds_t)ceil((1e6 * count) / sample_frequency));
return count;
}
size_t SoundNull::Read(double *buf, size_t count)
{
memset(buf, 0, count * sizeof(*buf));
if (capture)
writeCapture(buf, count);
if (playback) {
readPlayback(buf, count);
if (progdefaults.EnableMixer) {
double vol = valRcvMixer->value();
for (size_t i = 0; i < count; i++)
buf[i] *= vol;
}
}
usleep((useconds_t)ceil((1e6 * count) / sample_frequency));
return count;
}

Wyświetl plik

@ -294,8 +294,6 @@ void trx_start_modem(modem *m)
trx_state = STATE_NEW_MODEM;
}
string trx_scdev;
void trx_reset_loop()
{
if (scard) {
@ -305,20 +303,23 @@ void trx_reset_loop()
switch (progdefaults.btnAudioIOis) {
#if USE_OSS
case 0:
scard = new SoundOSS(trx_scdev.c_str());
case SND_IDX_OSS:
scard = new SoundOSS(scDevice[0].c_str());
break;
#endif
#if USE_PORTAUDIO
case 1:
scard = new SoundPort(trx_scdev.c_str());
case SND_IDX_PORT:
scard = new SoundPort(scDevice[0].c_str(), scDevice[1].c_str());
break;
#endif
#if USE_PULSEAUDIO
case 2:
scard = new SoundPulse(trx_scdev.c_str());
case SND_IDX_PULSE:
scard = new SoundPulse(scDevice[0].c_str());
break;
#endif
case SND_IDX_NULL:
scard = new SoundNull;
break;
default:
abort();
}
@ -326,9 +327,8 @@ void trx_reset_loop()
trx_state = STATE_RX;
}
void trx_reset(const char *scdev)
void trx_reset(void)
{
trx_scdev = scdev;
trx_state = STATE_RESTART;
}
@ -365,7 +365,7 @@ void trx_start_macro_timer()
FL_UNLOCK();
}
void trx_start(const char *scdev)
void trx_start(void)
{
if (trxrunning) {
std::cout<< "trx already running!\n"; fflush(stdout);
@ -376,20 +376,23 @@ void trx_start(const char *scdev)
switch (progdefaults.btnAudioIOis) {
#if USE_OSS
case 0:
scard = new SoundOSS(scdev);
case SND_IDX_OSS:
scard = new SoundOSS(scDevice[0].c_str());
break;
#endif
#if USE_PORTAUDIO
case 1:
scard = new SoundPort(scdev);
case SND_IDX_PORT:
scard = new SoundPort(scDevice[0].c_str(), scDevice[1].c_str());
break;
#endif
#if USE_PULSEAUDIO
case 2:
scard = new SoundPulse(scdev);
case SND_IDX_PULSE:
scard = new SoundPulse(scDevice[0].c_str());
break;
#endif
case SND_IDX_NULL:
scard = new SoundNull;
break;
default:
abort();
}

Wyświetl plik

@ -291,7 +291,7 @@ void FTextBase::adjust_colours(void)
Fl_Menu_Item FTextView::view_menu[] = {
{ "@-4>> &QRZ this call", 0, 0 },
{ "@-4>> &Look up call", 0, 0 },
{ "@-9-> &Call", 0, 0 },
{ "@-9-> &Name", 0, 0 },
{ "@-9-> QT&H", 0, 0 },
@ -459,8 +459,8 @@ void FTextView::menu_cb(int val)
char *s;
case RX_MENU_QRZ_THIS:
menu_cb(RX_MENU_CALL);
extern void QRZquery();
QRZquery();
extern void CALLSIGNquery();
CALLSIGNquery();
break;
case RX_MENU_CALL:
s = get_word(popx, popy);