Merge pull request #3 from corrados/master

update master
This commit is contained in:
Miguel de Matos 2020-05-21 22:38:59 +01:00 committed by GitHub
commit 7fdd0c33de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
86 changed files with 5317 additions and 1545 deletions

View file

@ -1,17 +1,23 @@
3.5.4git 3.5.4git
TODO server list split on query - introduce genre-based server lists (#139)
TODO Keep lrelease? Does it work as expected? - implement panning for channels, coded by tarmoj (#52, #145)
TODO fix Linux deploy script -> gives errors right now - added an indicator that another client has muted me (#257)
TODO WIP support internationalization - duplicate Central Server type dropdown to Connection Setup (#157)
TODO implement panning for channels (Ticket #52, #145) - added vocal bass/tenor/alto/soprano instrument icons created by Alberstein8 (#131)
- support intermediate Reaper RPP file while recording, coded by pljones (#170)
- save client settings on Linux cmdline termination signal, coded by pljones (#70)
TODO show mute state of others
@ -26,23 +32,23 @@ TODO show mute state of others
- for CoreAudio and 4 channel input, support mixing channels 1&2 with 3&4 - for CoreAudio and 4 channel input, support mixing channels 1&2 with 3&4
- added bassoon/oboe/harp instrument icons created by dszgit, - added bassoon/oboe/harp instrument icons created by dszgit,
congas/bongo created by bspeer (Ticket #131) congas/bongo created by bspeer (#131)
- link to docs from application Help menu (Ticket #90) - link to docs from application Help menu (#90)
- support Mac CoreAudio aggregated devices (Ticket #138) - support Mac CoreAudio aggregated devices (#138)
- added translations: French by trebmuh, Portuguese by Snayler, - added translations: French by trebmuh, Portuguese by Snayler,
Spanish by ignotus666, Dutch by jerogee, German by corrados (Ticket #77) Spanish by ignotus666, Dutch by jerogee, German by corrados (#77)
- new design for the About dialog (Ticket #189) - new design for the About dialog (#189)
- new command line option -d to disconnect all clients on shutdown of the server (Ticket #161) - new command line option -d to disconnect all clients on shutdown of the server (#161)
- bug fix: for mono capture jack audio interface Jamulus complains it - bug fix: for mono capture jack audio interface Jamulus complains it
cannot make connections (Ticket #137) cannot make connections (#137)
- bug fix: fixed that Jamulus segfaults when jackd is restarted (Ticket #122, #127) - bug fix: fixed that Jamulus segfaults when jackd is restarted (#122, #127)
- bug fix: better handling of disconnect message in the client - bug fix: better handling of disconnect message in the client
@ -57,21 +63,21 @@ TODO show mute state of others
- improved Mac installer, coded by doloopuntil - improved Mac installer, coded by doloopuntil
- support to open ASIO driver setup(s) if startup failed due to incorrect driver settings (Ticket #117) - support to open ASIO driver setup(s) if startup failed due to incorrect driver settings (#117)
- added -v/--version command line argument to output version information (Ticket #121) - added -v/--version command line argument to output version information (#121)
- added bodhran and other instrument icons, bodhran created by bomm (Ticket #131) - added bodhran and other instrument icons, bodhran created by bomm (#131)
- bug fix: if small network buffers are used we get much better audio quality when drop outs occur - bug fix: if small network buffers are used we get much better audio quality when drop outs occur
- bug fix: if names given with the -o option were too long, the server registration failed (Ticket #91) - bug fix: if names given with the -o option were too long, the server registration failed (#91)
- bug fix: audio level changes if Buffer Delay is changed (Ticket #106) - bug fix: audio level changes if Buffer Delay is changed (#106)
- bug fix: do not reset fader level meters if number of clients change - bug fix: do not reset fader level meters if number of clients change
- bug fix: fixed a crash with JackRouter 64 bit ASIO driver (Ticket #93, thanks to elliotclee) - bug fix: fixed a crash with JackRouter 64 bit ASIO driver (#93, thanks to elliotclee)
3.5.1 (2020-04-18) 3.5.1 (2020-04-18)
@ -103,21 +109,21 @@ TODO show mute state of others
- the unit of the mixer faders is now dB using the range -50 dB to 0 dB - the unit of the mixer faders is now dB using the range -50 dB to 0 dB
- increased LED luminance (Ticket #71) - increased LED luminance (#71)
- bug fix: the server welcome message may appear twice if the server list was double clicked - bug fix: the server welcome message may appear twice if the server list was double clicked
3.4.7 (2020-04-11) 3.4.7 (2020-04-11)
- added support for alternative Central Servers to solve the 200 server registration limit (Ticket #50) - added support for alternative Central Servers to solve the 200 server registration limit (#50)
- added support for 64 samples frame size in the server (if server runs in 64 or 128 samples - added support for 64 samples frame size in the server (if server runs in 64 or 128 samples
mode it is still compatible to both, 64 and 128 samples frame size clients) mode it is still compatible to both, 64 and 128 samples frame size clients)
- added multichannel CoreAudio support, coded by emlynmac (#44) - added multichannel CoreAudio support, coded by emlynmac (#44)
- fixed server not visible if in same local network, coded by pljones (Ticket #27) - fixed server not visible if in same local network, coded by pljones (#27)
3.4.6 (2020-04-09) 3.4.6 (2020-04-09)
@ -128,7 +134,7 @@ TODO show mute state of others
- store fader mute state in the ini file, coded by doloopuntil - store fader mute state in the ini file, coded by doloopuntil
- fixed low-res icon issue (Ticket #28) - fixed low-res icon issue (#28)
3.4.5 (2020-04-04) 3.4.5 (2020-04-04)
@ -150,7 +156,7 @@ TODO show mute state of others
- added support for controlling the audio mixer faders with a MIDI controller (MacOS and Linux) - added support for controlling the audio mixer faders with a MIDI controller (MacOS and Linux)
- added command line argument for disabling auto jack connection (Ticket #49) - added command line argument for disabling auto jack connection (#49)
- audio recording for the server, coded by pljones - audio recording for the server, coded by pljones

View file

@ -2,7 +2,7 @@
Installing Jamulus Installing Jamulus
============================ ============================
[Please see this overview](https://github.com/corrados/jamulus/wiki/Software-Manual) containing instructions for installing and using Jamulus for your platform. [Please see this overview](https://github.com/corrados/jamulus/wiki/Getting-Started) containing instructions for installing and using Jamulus for your platform.
Compiling Jamulus Compiling Jamulus

View file

@ -8,8 +8,7 @@ contains(CONFIG, "noupcasename") {
CONFIG += qt \ CONFIG += qt \
thread \ thread \
release \ release
lrelease
QT += widgets \ QT += widgets \
network \ network \
@ -19,7 +18,8 @@ TRANSLATIONS = src/res/translation/translation_de_DE.ts \
src/res/translation/translation_fr_FR.ts \ src/res/translation/translation_fr_FR.ts \
src/res/translation/translation_pt_PT.ts \ src/res/translation/translation_pt_PT.ts \
src/res/translation/translation_es_ES.ts \ src/res/translation/translation_es_ES.ts \
src/res/translation/translation_nl_NL.ts src/res/translation/translation_nl_NL.ts \
src/res/translation/translation_it_IT.ts
INCLUDEPATH += src INCLUDEPATH += src
@ -301,6 +301,16 @@ DISTFILES_OBOE += libs/oboe/AUTHORS \
android/AndroidManifest.xml \ android/AndroidManifest.xml \
android/sound.h \ android/sound.h \
android/sound.cpp android/sound.cpp
isEmpty(PREFIX) {
PREFIX = /usr/local
}
isEmpty(BINDIR) {
BINDIR = bin
}
BINDIR = $$absolute_path($$BINDIR, $$PREFIX)
INSTALLS += target
target.path = $$BINDIR
} }
RCC_DIR = src/res RCC_DIR = src/res
@ -355,7 +365,6 @@ HEADERS_OPUS = libs/opus/celt/arch.h \
libs/opus/celt/kiss_fft.h \ libs/opus/celt/kiss_fft.h \
libs/opus/celt/laplace.h \ libs/opus/celt/laplace.h \
libs/opus/celt/mathops.h \ libs/opus/celt/mathops.h \
libs/opus/celt/mdct.c \
libs/opus/celt/mdct.h \ libs/opus/celt/mdct.h \
libs/opus/celt/mfrngcod.h \ libs/opus/celt/mfrngcod.h \
libs/opus/celt/modes.h \ libs/opus/celt/modes.h \
@ -365,7 +374,6 @@ HEADERS_OPUS = libs/opus/celt/arch.h \
libs/opus/celt/rate.h \ libs/opus/celt/rate.h \
libs/opus/celt/stack_alloc.h \ libs/opus/celt/stack_alloc.h \
libs/opus/celt/static_modes_float.h \ libs/opus/celt/static_modes_float.h \
libs/opus/celt/vq.c \
libs/opus/celt/vq.h \ libs/opus/celt/vq.h \
libs/opus/celt/_kiss_fft_guts.h \ libs/opus/celt/_kiss_fft_guts.h \
libs/opus/include/opus.h \ libs/opus/include/opus.h \
@ -373,7 +381,6 @@ HEADERS_OPUS = libs/opus/celt/arch.h \
libs/opus/include/opus_defines.h \ libs/opus/include/opus_defines.h \
libs/opus/include/opus_types.h \ libs/opus/include/opus_types.h \
libs/opus/silk/API.h \ libs/opus/silk/API.h \
libs/opus/silk/CNG.c \
libs/opus/silk/control.h \ libs/opus/silk/control.h \
libs/opus/silk/debug.h \ libs/opus/silk/debug.h \
libs/opus/silk/define.h \ libs/opus/silk/define.h \
@ -386,10 +393,8 @@ HEADERS_OPUS = libs/opus/celt/arch.h \
libs/opus/silk/MacroDebug.h \ libs/opus/silk/MacroDebug.h \
libs/opus/silk/macros.h \ libs/opus/silk/macros.h \
libs/opus/silk/main.h \ libs/opus/silk/main.h \
libs/opus/silk/NSQ.c \
libs/opus/silk/NSQ.h \ libs/opus/silk/NSQ.h \
libs/opus/silk/pitch_est_defines.h \ libs/opus/silk/pitch_est_defines.h \
libs/opus/silk/PLC.c \
libs/opus/silk/PLC.h \ libs/opus/silk/PLC.h \
libs/opus/silk/resampler_private.h \ libs/opus/silk/resampler_private.h \
libs/opus/silk/resampler_rom.h \ libs/opus/silk/resampler_rom.h \
@ -399,7 +404,6 @@ HEADERS_OPUS = libs/opus/celt/arch.h \
libs/opus/silk/tables.h \ libs/opus/silk/tables.h \
libs/opus/silk/tuning_parameters.h \ libs/opus/silk/tuning_parameters.h \
libs/opus/silk/typedef.h \ libs/opus/silk/typedef.h \
libs/opus/silk/VAD.c \
libs/opus/src/analysis.h \ libs/opus/src/analysis.h \
libs/opus/src/mlp.h \ libs/opus/src/mlp.h \
libs/opus/src/opus_private.h \ libs/opus/src/opus_private.h \
@ -622,12 +626,6 @@ DISTFILES += ChangeLog \
COPYING \ COPYING \
INSTALL.md \ INSTALL.md \
README.md \ README.md \
android/build.gradle \
android/gradle/wrapper/gradle-wrapper.jar \
android/gradle/wrapper/gradle-wrapper.properties \
android/gradlew \
android/gradlew.bat \
android/res/values/libs.xml \
src/res/CLEDBlack.png \ src/res/CLEDBlack.png \
src/res/CLEDBlackSmall.png \ src/res/CLEDBlackSmall.png \
src/res/CLEDDisabledSmall.png \ src/res/CLEDDisabledSmall.png \
@ -678,34 +676,34 @@ DISTFILES += ChangeLog \
src/res/VRLEDRedSmall.png \ src/res/VRLEDRedSmall.png \
src/res/VRLEDYellow.png \ src/res/VRLEDYellow.png \
src/res/VRLEDYellowSmall.png \ src/res/VRLEDYellowSmall.png \
src/res/instruments/instraccordeon.png \ src/res/instruments/accordeon.png \
src/res/instruments/instraguitar.png \ src/res/instruments/aguitar.png \
src/res/instruments/instrbassguitar.png \ src/res/instruments/bassguitar.png \
src/res/instruments/instrcello.png \ src/res/instruments/cello.png \
src/res/instruments/instrclarinet.png \ src/res/instruments/clarinet.png \
src/res/instruments/instrdjembe.png \ src/res/instruments/djembe.png \
src/res/instruments/instrdoublebass.png \ src/res/instruments/doublebass.png \
src/res/instruments/instrdrumset.png \ src/res/instruments/drumset.png \
src/res/instruments/instreguitar.png \ src/res/instruments/eguitar.png \
src/res/instruments/instrflute.png \ src/res/instruments/flute.png \
src/res/instruments/instrfrenchhorn.png \ src/res/instruments/frenchhorn.png \
src/res/instruments/instrgrandpiano.png \ src/res/instruments/grandpiano.png \
src/res/instruments/instrharmonica.png \ src/res/instruments/harmonica.png \
src/res/instruments/instrkeyboard.png \ src/res/instruments/keyboard.png \
src/res/instruments/instrlistener.png \ src/res/instruments/listener.png \
src/res/instruments/instrmicrophone.png \ src/res/instruments/microphone.png \
src/res/instruments/instrnone.png \ src/res/instruments/none.png \
src/res/instruments/instrrecorder.png \ src/res/instruments/recorder.png \
src/res/instruments/instrsaxophone.png \ src/res/instruments/saxophone.png \
src/res/instruments/instrstreamer.png \ src/res/instruments/streamer.png \
src/res/instruments/instrsynthesizer.png \ src/res/instruments/synthesizer.png \
src/res/instruments/instrtrombone.png \ src/res/instruments/trombone.png \
src/res/instruments/instrtrumpet.png \ src/res/instruments/trumpet.png \
src/res/instruments/instrtuba.png \ src/res/instruments/tuba.png \
src/res/instruments/instrviolin.png \ src/res/instruments/violin.png \
src/res/instruments/instrvocal.png \ src/res/instruments/vocal.png \
src/res/instruments/instrguitarvocal.png \ src/res/instruments/guitarvocal.png \
src/res/instruments/instrkeyboardvocal.png \ src/res/instruments/keyboardvocal.png \
src/res/instruments/bodhran.svg \ src/res/instruments/bodhran.svg \
src/res/instruments/bodhran.png \ src/res/instruments/bodhran.png \
src/res/instruments/bassoon.svg \ src/res/instruments/bassoon.svg \
@ -719,6 +717,10 @@ DISTFILES += ChangeLog \
src/res/instruments/congas.png \ src/res/instruments/congas.png \
src/res/instruments/bongo.svg \ src/res/instruments/bongo.svg \
src/res/instruments/bongo.png \ src/res/instruments/bongo.png \
src/res/instruments/vocalbass.png \
src/res/instruments/vocaltenor.png \
src/res/instruments/vocalalto.png \
src/res/instruments/vocalsoprano.png \
src/res/flags/flagnone.png \ src/res/flags/flagnone.png \
src/res/flags/ad.png \ src/res/flags/ad.png \
src/res/flags/ae.png \ src/res/flags/ae.png \

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<manifest package="org.qtproject.jamulus" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto"> <manifest package="com.github.corrados.jamulus" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
@ -18,9 +18,8 @@
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Jamulus" android:extractNativeLibs="true"> <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:extractNativeLibs="true" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="@string/app_name" android:screenOrientation="landscape" android:launchMode="singleTop"> <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="landscape" android:launchMode="singleTop">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
@ -30,7 +29,7 @@
<!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ --> <!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
<!-- Application arguments --> <!-- Application arguments -->
<meta-data android:name="android.app.lib_name" android:value="Jamulus"/> <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/> <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/> <meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -23,9 +23,6 @@ Depends:
${shlibs:Depends}, ${shlibs:Depends},
${misc:Depends}, ${misc:Depends},
adduser, adduser,
jackd,
qt5-default,
qtchooser,
Description: Low latency Audio Server/Client Description: Low latency Audio Server/Client
The Jamulus software enables musicians to perform real-time jam sessions over The Jamulus software enables musicians to perform real-time jam sessions over
the internet. There is one server running the Jamulus server software which the internet. There is one server running the Jamulus server software which

View file

@ -1,5 +1,5 @@
version=4 version=4
# GitHub hosted projects # GitHub hosted projects
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%@PACKAGE@-$1.tar.gz%" \ opts=uversionmangle=s%_%.%g,filenamemangle=s%(?:.*?)?(r\d[\d_]*)\.tar\.gz%@PACKAGE@-$1.tar.gz% \
https://github.com/corrados/jamulus/tags \ https://github.com/corrados/jamulus/tags \
(?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate (?:.*?/)?r(\d[\d_]*)\.tar\.gz debian uupdate

153
src/audiomixerboard.cpp Executable file → Normal file
View file

@ -39,6 +39,9 @@ CChannelFader::CChannelFader ( QWidget* pNW,
pLevelsBox = new QWidget ( pFrame ); pLevelsBox = new QWidget ( pFrame );
plbrChannelLevel = new CMultiColorLEDBar ( pLevelsBox ); plbrChannelLevel = new CMultiColorLEDBar ( pLevelsBox );
pFader = new QSlider ( Qt::Vertical, pLevelsBox ); pFader = new QSlider ( Qt::Vertical, pLevelsBox );
pPan = new QDial ( pLevelsBox );
pPanLabel = new QLabel ( tr ( "Pan" ) , pLevelsBox );
pInfoLabel = new QLabel ( "", pLevelsBox );
pMuteSoloBox = new QWidget ( pFrame ); pMuteSoloBox = new QWidget ( pFrame );
pcbMute = new QCheckBox ( tr ( "Mute" ), pMuteSoloBox ); pcbMute = new QCheckBox ( tr ( "Mute" ), pMuteSoloBox );
@ -54,6 +57,8 @@ CChannelFader::CChannelFader ( QWidget* pNW,
QVBoxLayout* pMuteSoloGrid = new QVBoxLayout ( pMuteSoloBox ); QVBoxLayout* pMuteSoloGrid = new QVBoxLayout ( pMuteSoloBox );
QHBoxLayout* pLabelGrid = new QHBoxLayout ( pLabelInstBox ); QHBoxLayout* pLabelGrid = new QHBoxLayout ( pLabelInstBox );
QVBoxLayout* pLabelPictGrid = new QVBoxLayout ( ); QVBoxLayout* pLabelPictGrid = new QVBoxLayout ( );
QVBoxLayout* pPanGrid = new QVBoxLayout ( );
QHBoxLayout* pPanInfoGrid = new QHBoxLayout ( );
// setup channel level // setup channel level
plbrChannelLevel->setContentsMargins ( 0, 3, 2, 3 ); plbrChannelLevel->setContentsMargins ( 0, 3, 2, 3 );
@ -63,6 +68,17 @@ CChannelFader::CChannelFader ( QWidget* pNW,
pFader->setTickPosition ( QSlider::TicksBothSides ); pFader->setTickPosition ( QSlider::TicksBothSides );
pFader->setRange ( 0, AUD_MIX_FADER_MAX ); pFader->setRange ( 0, AUD_MIX_FADER_MAX );
pFader->setTickInterval ( AUD_MIX_FADER_MAX / 9 ); pFader->setTickInterval ( AUD_MIX_FADER_MAX / 9 );
pFader->setMinimumHeight ( 75 );
// setup panning control
pPan->setRange ( 0, AUD_MIX_PAN_MAX );
pPan->setValue ( AUD_MIX_PAN_MAX / 2 );
pPan->setFixedSize ( 55, 55 );
pPan->setNotchesVisible ( true );
pPanInfoGrid->addWidget ( pPanLabel, 0, Qt::AlignLeft );
pPanInfoGrid->addWidget ( pInfoLabel );
pPanGrid->addLayout ( pPanInfoGrid );
pPanGrid->addWidget ( pPan, 0, Qt::AlignHCenter );
// setup fader tag label (black bold text which is centered) // setup fader tag label (black bold text which is centered)
plblLabel->setTextFormat ( Qt::PlainText ); plblLabel->setTextFormat ( Qt::PlainText );
@ -75,6 +91,9 @@ CChannelFader::CChannelFader ( QWidget* pNW,
// set margins of the layouts to zero to get maximum space for the controls // set margins of the layouts to zero to get maximum space for the controls
pMainGrid->setContentsMargins ( 0, 0, 0, 0 ); pMainGrid->setContentsMargins ( 0, 0, 0, 0 );
pPanGrid->setContentsMargins ( 0, 0, 0, 0 );
pPanGrid->setSpacing ( 0 ); // only minimal space
pLevelsGrid->setContentsMargins ( 0, 0, 0, 0 ); pLevelsGrid->setContentsMargins ( 0, 0, 0, 0 );
pLevelsGrid->setSpacing ( 0 ); // only minimal space pLevelsGrid->setSpacing ( 0 ); // only minimal space
@ -96,6 +115,7 @@ CChannelFader::CChannelFader ( QWidget* pNW,
pMuteSoloGrid->addWidget ( pcbMute, 0, Qt::AlignLeft ); pMuteSoloGrid->addWidget ( pcbMute, 0, Qt::AlignLeft );
pMuteSoloGrid->addWidget ( pcbSolo, 0, Qt::AlignLeft ); pMuteSoloGrid->addWidget ( pcbSolo, 0, Qt::AlignLeft );
pMainGrid->addLayout ( pPanGrid );
pMainGrid->addWidget ( pLevelsBox, 0, Qt::AlignHCenter ); pMainGrid->addWidget ( pLevelsBox, 0, Qt::AlignHCenter );
pMainGrid->addWidget ( pMuteSoloBox, 0, Qt::AlignHCenter ); pMainGrid->addWidget ( pMuteSoloBox, 0, Qt::AlignHCenter );
pMainGrid->addWidget ( pLabelInstBox ); pMainGrid->addWidget ( pLabelInstBox );
@ -119,6 +139,18 @@ CChannelFader::CChannelFader ( QWidget* pNW,
pFader->setAccessibleName ( tr ( "Local mix level setting of the current audio " pFader->setAccessibleName ( tr ( "Local mix level setting of the current audio "
"channel at the server" ) ); "channel at the server" ) );
pInfoLabel->setWhatsThis ( "<b>" + tr ( "Status Indicator" ) + ":</b> " + tr (
"Shows a status indication about the client which is assigned to this channel. "
"Supported indicators are:" ) + "<ul><li>" + tr (
"Speaker with cancellation stroke: Indicates that the other client has muted you." ) +
"</li></ul>" );
pInfoLabel->setAccessibleName ( tr ( "Status indicator label" ) );
pPan->setWhatsThis ( "<b>" + tr ( "Panning" ) + ":</b> " + tr (
"Sets the panning position from Left to Right of the channel. "
"Works only in stereo or preferably mono in/stereo out mode." ) );
pPan->setAccessibleName ( tr ( "Local panning position of the current audio channel at the server" ) );
pcbMute->setWhatsThis ( "<b>" + tr ( "Mute" ) + ":</b> " + tr ( pcbMute->setWhatsThis ( "<b>" + tr ( "Mute" ) + ":</b> " + tr (
"With the Mute checkbox, the audio channel can be muted." ) ); "With the Mute checkbox, the audio channel can be muted." ) );
pcbMute->setAccessibleName ( tr ( "Mute button" ) ); pcbMute->setAccessibleName ( tr ( "Mute button" ) );
@ -145,6 +177,9 @@ CChannelFader::CChannelFader ( QWidget* pNW,
QObject::connect ( pFader, SIGNAL ( valueChanged ( int ) ), QObject::connect ( pFader, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnLevelValueChanged ( int ) ) ); this, SLOT ( OnLevelValueChanged ( int ) ) );
QObject::connect ( pPan, SIGNAL ( valueChanged ( int ) ),
this, SLOT ( OnPanValueChanged ( int ) ) );
QObject::connect ( pcbMute, SIGNAL ( stateChanged ( int ) ), QObject::connect ( pcbMute, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnMuteStateChanged ( int ) ) ); this, SLOT ( OnMuteStateChanged ( int ) ) );
@ -172,6 +207,7 @@ void CChannelFader::SetGUIDesign ( const EGUIDesign eNewDesign )
" padding-bottom: -15px; }" " padding-bottom: -15px; }"
"QSlider::handle { image: url(:/png/fader/res/faderhandle.png); }" ); "QSlider::handle { image: url(:/png/fader/res/faderhandle.png); }" );
pPanLabel->setText ( tr ( "PAN" ) );
pcbMute->setText ( tr ( "MUTE" ) ); pcbMute->setText ( tr ( "MUTE" ) );
pcbSolo->setText ( tr ( "SOLO" ) ); pcbSolo->setText ( tr ( "SOLO" ) );
plbrChannelLevel->SetLevelMeterType ( CMultiColorLEDBar::MT_LED ); plbrChannelLevel->SetLevelMeterType ( CMultiColorLEDBar::MT_LED );
@ -180,6 +216,7 @@ void CChannelFader::SetGUIDesign ( const EGUIDesign eNewDesign )
default: default:
// reset style sheet and set original paramters // reset style sheet and set original paramters
pFader->setStyleSheet ( "" ); pFader->setStyleSheet ( "" );
pPanLabel->setText ( tr ( "Pan" ) );
pcbMute->setText ( tr ( "Mute" ) ); pcbMute->setText ( tr ( "Mute" ) );
pcbSolo->setText ( tr ( "Solo" ) ); pcbSolo->setText ( tr ( "Solo" ) );
plbrChannelLevel->SetLevelMeterType ( CMultiColorLEDBar::MT_BAR ); plbrChannelLevel->SetLevelMeterType ( CMultiColorLEDBar::MT_BAR );
@ -197,6 +234,13 @@ bool CChannelFader::GetDisplayChannelLevel()
return !plbrChannelLevel->isHidden(); return !plbrChannelLevel->isHidden();
} }
void CChannelFader::SetDisplayPans ( const bool eNDP )
{
pInfoLabel->setHidden ( !eNDP );
pPanLabel->setHidden ( !eNDP );
pPan->setHidden ( !eNDP );
}
void CChannelFader::SetupFaderTag ( const ESkillLevel eSkillLevel ) void CChannelFader::SetupFaderTag ( const ESkillLevel eSkillLevel )
{ {
// setup group box for label/instrument picture: set a thick black border // setup group box for label/instrument picture: set a thick black border
@ -243,8 +287,12 @@ void CChannelFader::SetupFaderTag ( const ESkillLevel eSkillLevel )
void CChannelFader::Reset() void CChannelFader::Reset()
{ {
// init gain value -> maximum value as definition according to server // general initializations
SetRemoteFaderIsMute ( false );
// init gain and pan value -> maximum value as definition according to server
pFader->setValue ( AUD_MIX_FADER_MAX ); pFader->setValue ( AUD_MIX_FADER_MAX );
pPan->setValue ( AUD_MIX_PAN_MAX / 2 );
// reset mute/solo check boxes and level meter // reset mute/solo check boxes and level meter
pcbMute->setChecked ( false ); pcbMute->setChecked ( false );
@ -282,6 +330,18 @@ void CChannelFader::SetFaderLevel ( const int iLevel )
} }
} }
void CChannelFader::SetPanValue ( const int iPan )
{
// first make a range check
if ( ( iPan >= 0 ) && ( iPan <= AUD_MIX_PAN_MAX ) )
{
// we set the new fader level in the GUI (slider control) and also tell the
// server about the change
pPan->setValue ( iPan );
SendPanValueToServer ( iPan );
}
}
void CChannelFader::SetFaderIsSolo ( const bool bIsSolo ) void CChannelFader::SetFaderIsSolo ( const bool bIsSolo )
{ {
// changing the state automatically emits the signal, too // changing the state automatically emits the signal, too
@ -294,6 +354,19 @@ void CChannelFader::SetFaderIsMute ( const bool bIsMute )
pcbMute->setChecked ( bIsMute ); pcbMute->setChecked ( bIsMute );
} }
void CChannelFader::SetRemoteFaderIsMute ( const bool bIsMute )
{
if ( bIsMute )
{
// show orange utf8 SPEAKER WITH CANCELLATION STROKE (U+1F507)
pInfoLabel->setText ( "<font color=""orange"">&#128263;</font>" );
}
else
{
pInfoLabel->setText ( "" );
}
}
void CChannelFader::SendFaderLevelToServer ( const int iLevel ) void CChannelFader::SendFaderLevelToServer ( const int iLevel )
{ {
// if mute flag is set or other channel is on solo, do not apply the new // if mute flag is set or other channel is on solo, do not apply the new
@ -307,6 +380,11 @@ void CChannelFader::SendFaderLevelToServer ( const int iLevel )
} }
} }
void CChannelFader::SendPanValueToServer ( const int iPan )
{
emit panValueChanged ( static_cast<double> ( iPan ) / AUD_MIX_PAN_MAX );
}
void CChannelFader::OnMuteStateChanged ( int value ) void CChannelFader::OnMuteStateChanged ( int value )
{ {
// call muting function // call muting function
@ -522,9 +600,10 @@ double CChannelFader::CalcFaderGain ( const int value )
* CAudioMixerBoard * * CAudioMixerBoard *
\******************************************************************************/ \******************************************************************************/
CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent, Qt::WindowFlags ) : CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent, Qt::WindowFlags ) :
QScrollArea ( parent ), QGroupBox ( parent ),
vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ), vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ),
vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ), vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ),
vecStoredPanValues ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_PAN_MAX / 2 ),
vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ),
vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ),
iNewClientFaderLevel ( 100 ), iNewClientFaderLevel ( 100 ),
@ -532,8 +611,10 @@ CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent, Qt::WindowFlags ) :
strServerName ( "" ) strServerName ( "" )
{ {
// add group box and hboxlayout // add group box and hboxlayout
pGroupBox = new QGroupBox(); // will be added to the scroll area which is then the parent QHBoxLayout* pGroupBoxLayout = new QHBoxLayout ( this );
pMainLayout = new QHBoxLayout ( pGroupBox ); QWidget* pMixerWidget = new QWidget(); // will be added to the scroll area which is then the parent
pScrollArea = new CMixerBoardScrollArea ( this );
pMainLayout = new QHBoxLayout ( pMixerWidget );
// set title text (default: no server given) // set title text (default: no server given)
SetServerName ( "" ); SetServerName ( "" );
@ -550,13 +631,15 @@ CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent, Qt::WindowFlags ) :
// insert horizontal spacer // insert horizontal spacer
pMainLayout->addItem ( new QSpacerItem ( 0, 0, QSizePolicy::Expanding ) ); pMainLayout->addItem ( new QSpacerItem ( 0, 0, QSizePolicy::Expanding ) );
// set margins of the layout to zero to get maximum space for the controls
pGroupBoxLayout->setContentsMargins ( 0, 0, 0, 1 ); // note: to avoid problems at the botton, use a small margin for that
// add the group box to the scroll area // add the group box to the scroll area
setMinimumWidth ( 200 ); // at least two faders shall be visible pScrollArea->setMinimumWidth ( 200 ); // at least two faders shall be visible
setWidget ( pGroupBox ); pScrollArea->setWidget ( pMixerWidget );
setWidgetResizable ( true ); // make sure it fills the entire scroll area pScrollArea->setWidgetResizable ( true ); // make sure it fills the entire scroll area
setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); pScrollArea->setFrameShape ( QFrame::NoFrame );
setHorizontalScrollBarPolicy ( Qt::ScrollBarAsNeeded ); pGroupBoxLayout->addWidget ( pScrollArea );
setFrameShape ( QFrame::NoFrame );
// Connections ------------------------------------------------------------- // Connections -------------------------------------------------------------
@ -571,12 +654,18 @@ inline void CAudioMixerBoard::connectFaderSignalsToMixerBoardSlots()
void ( CAudioMixerBoard::* pGainValueChanged )( double ) = void ( CAudioMixerBoard::* pGainValueChanged )( double ) =
&CAudioMixerBoardSlots<slotId>::OnChGainValueChanged; &CAudioMixerBoardSlots<slotId>::OnChGainValueChanged;
void ( CAudioMixerBoard::* pPanValueChanged )( double ) =
&CAudioMixerBoardSlots<slotId>::OnChPanValueChanged;
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::soloStateChanged, QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::soloStateChanged,
this, &CAudioMixerBoard::UpdateSoloStates ); this, &CAudioMixerBoard::UpdateSoloStates );
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::gainValueChanged, QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::gainValueChanged,
this, pGainValueChanged ); this, pGainValueChanged );
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::panValueChanged,
this, pPanValueChanged );
connectFaderSignalsToMixerBoardSlots<slotId - 1>(); connectFaderSignalsToMixerBoardSlots<slotId - 1>();
}; };
@ -591,7 +680,7 @@ void CAudioMixerBoard::SetServerName ( const QString& strNewServerName )
if ( strServerName.isEmpty() ) if ( strServerName.isEmpty() )
{ {
// no connection or connection was reset: show default title // no connection or connection was reset: show default title
pGroupBox->setTitle ( tr ( "Server" ) ); setTitle ( tr ( "Server" ) );
} }
else else
{ {
@ -600,7 +689,7 @@ void CAudioMixerBoard::SetServerName ( const QString& strNewServerName )
// list was received, the connection was successful and the title is updated // list was received, the connection was successful and the title is updated
// with the correct server name. Make sure to choose a "try to connect" title // with the correct server name. Make sure to choose a "try to connect" title
// which is most striking (we use filled blocks and upper case letters). // which is most striking (we use filled blocks and upper case letters).
pGroupBox->setTitle ( u8"\u2588\u2588\u2588\u2588\u2588 " + tr ( "T R Y I N G T O C O N N E C T" ) + u8" \u2588\u2588\u2588\u2588\u2588" ); setTitle ( u8"\u2588\u2588\u2588\u2588\u2588 " + tr ( "T R Y I N G T O C O N N E C T" ) + u8" \u2588\u2588\u2588\u2588\u2588" );
} }
} }
@ -629,6 +718,14 @@ void CAudioMixerBoard::SetDisplayChannelLevels ( const bool eNDCL )
} }
} }
void CAudioMixerBoard::SetPanIsSupported()
{
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
{
vecpChanFader[i]->SetDisplayPans ( true );
}
}
void CAudioMixerBoard::HideAll() void CAudioMixerBoard::HideAll()
{ {
// make all controls invisible // make all controls invisible
@ -639,6 +736,7 @@ void CAudioMixerBoard::HideAll()
vecpChanFader[i]->SetChannelLevel ( 0 ); vecpChanFader[i]->SetChannelLevel ( 0 );
vecpChanFader[i]->SetDisplayChannelLevel ( false ); vecpChanFader[i]->SetDisplayChannelLevel ( false );
vecpChanFader[i]->SetDisplayPans ( false );
vecpChanFader[i]->Hide(); vecpChanFader[i]->Hide();
} }
@ -653,9 +751,9 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
{ {
// we want to set the server name only if the very first faders appear // we want to set the server name only if the very first faders appear
// in the audio mixer board to show a "try to connect" before // in the audio mixer board to show a "try to connect" before
if ( pGroupBox->title().compare ( strServerName ) ) if ( bNoFaderVisible )
{ {
pGroupBox->setTitle ( strServerName ); setTitle ( tr ( "Personal Mix at the Server: " ) + strServerName );
} }
// get number of connected clients // get number of connected clients
@ -700,15 +798,18 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
// the text has actually changed, search in the list of // the text has actually changed, search in the list of
// stored settings if we have a matching entry // stored settings if we have a matching entry
int iStoredFaderLevel; int iStoredFaderLevel;
int iStoredPanValue;
bool bStoredFaderIsSolo; bool bStoredFaderIsSolo;
bool bStoredFaderIsMute; bool bStoredFaderIsMute;
if ( GetStoredFaderSettings ( vecChanInfo[j], if ( GetStoredFaderSettings ( vecChanInfo[j],
iStoredFaderLevel, iStoredFaderLevel,
iStoredPanValue,
bStoredFaderIsSolo, bStoredFaderIsSolo,
bStoredFaderIsMute ) ) bStoredFaderIsMute ) )
{ {
vecpChanFader[i]->SetFaderLevel ( iStoredFaderLevel ); vecpChanFader[i]->SetFaderLevel ( iStoredFaderLevel );
vecpChanFader[i]->SetPanValue ( iStoredPanValue );
vecpChanFader[i]->SetFaderIsSolo ( bStoredFaderIsSolo ); vecpChanFader[i]->SetFaderIsSolo ( bStoredFaderIsSolo );
vecpChanFader[i]->SetFaderIsMute ( bStoredFaderIsMute ); vecpChanFader[i]->SetFaderIsMute ( bStoredFaderIsMute );
} }
@ -758,6 +859,19 @@ void CAudioMixerBoard::SetFaderLevel ( const int iChannelIdx,
} }
} }
void CAudioMixerBoard::SetRemoteFaderIsMute ( const int iChannelIdx,
const bool bIsMute )
{
// only apply remote mute state if channel index is valid and the fader is visible
if ( ( iChannelIdx >= 0 ) && ( iChannelIdx < MAX_NUM_CHANNELS ) )
{
if ( vecpChanFader[iChannelIdx]->IsVisible() )
{
vecpChanFader[iChannelIdx]->SetRemoteFaderIsMute ( bIsMute );
}
}
}
void CAudioMixerBoard::UpdateSoloStates() void CAudioMixerBoard::UpdateSoloStates()
{ {
// first check if any channel has a solo state active // first check if any channel has a solo state active
@ -789,6 +903,12 @@ void CAudioMixerBoard::UpdateGainValue ( const int iChannelIdx,
emit ChangeChanGain ( iChannelIdx, dValue ); emit ChangeChanGain ( iChannelIdx, dValue );
} }
void CAudioMixerBoard::UpdatePanValue ( const int iChannelIdx,
const double dValue )
{
emit ChangeChanPan ( iChannelIdx, dValue );
}
void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader ) void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
{ {
// if the fader was visible and the name is not empty, we store the old gain // if the fader was visible and the name is not empty, we store the old gain
@ -796,6 +916,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
!pChanFader->GetReceivedName().isEmpty() ) !pChanFader->GetReceivedName().isEmpty() )
{ {
CVector<int> viOldStoredFaderLevels ( vecStoredFaderLevels ); CVector<int> viOldStoredFaderLevels ( vecStoredFaderLevels );
CVector<int> viOldStoredPanValues ( vecStoredPanValues );
CVector<int> vbOldStoredFaderIsSolo ( vecStoredFaderIsSolo ); CVector<int> vbOldStoredFaderIsSolo ( vecStoredFaderIsSolo );
CVector<int> vbOldStoredFaderIsMute ( vecStoredFaderIsMute ); CVector<int> vbOldStoredFaderIsMute ( vecStoredFaderIsMute );
@ -809,6 +930,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
// current fader level and solo state is at the top of the list // current fader level and solo state is at the top of the list
vecStoredFaderLevels[0] = pChanFader->GetFaderLevel(); vecStoredFaderLevels[0] = pChanFader->GetFaderLevel();
vecStoredPanValues[0] = pChanFader->GetPanValue();
vecStoredFaderIsSolo[0] = pChanFader->IsSolo(); vecStoredFaderIsSolo[0] = pChanFader->IsSolo();
vecStoredFaderIsMute[0] = pChanFader->IsMute(); vecStoredFaderIsMute[0] = pChanFader->IsMute();
iTempListCnt = 1; iTempListCnt = 1;
@ -824,6 +946,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
if ( iIdx != iOldIdx ) if ( iIdx != iOldIdx )
{ {
vecStoredFaderLevels[iTempListCnt] = viOldStoredFaderLevels[iIdx]; vecStoredFaderLevels[iTempListCnt] = viOldStoredFaderLevels[iIdx];
vecStoredPanValues[iTempListCnt] = viOldStoredPanValues[iIdx];
vecStoredFaderIsSolo[iTempListCnt] = vbOldStoredFaderIsSolo[iIdx]; vecStoredFaderIsSolo[iTempListCnt] = vbOldStoredFaderIsSolo[iIdx];
vecStoredFaderIsMute[iTempListCnt] = vbOldStoredFaderIsMute[iIdx]; vecStoredFaderIsMute[iTempListCnt] = vbOldStoredFaderIsMute[iIdx];
@ -836,6 +959,7 @@ void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
bool CAudioMixerBoard::GetStoredFaderSettings ( const CChannelInfo& ChanInfo, bool CAudioMixerBoard::GetStoredFaderSettings ( const CChannelInfo& ChanInfo,
int& iStoredFaderLevel, int& iStoredFaderLevel,
int& iStoredPanValue,
bool& bStoredFaderIsSolo, bool& bStoredFaderIsSolo,
bool& bStoredFaderIsMute) bool& bStoredFaderIsMute)
{ {
@ -849,6 +973,7 @@ bool CAudioMixerBoard::GetStoredFaderSettings ( const CChannelInfo& ChanInfo,
{ {
// copy stored settings values // copy stored settings values
iStoredFaderLevel = vecStoredFaderLevels[iIdx]; iStoredFaderLevel = vecStoredFaderLevels[iIdx];
iStoredPanValue = vecStoredPanValues[iIdx];
bStoredFaderIsSolo = vecStoredFaderIsSolo[iIdx] != 0; bStoredFaderIsSolo = vecStoredFaderIsSolo[iIdx] != 0;
bStoredFaderIsMute = vecStoredFaderIsMute[iIdx] != 0; bStoredFaderIsMute = vecStoredFaderIsMute[iIdx] != 0;

43
src/audiomixerboard.h Executable file → Normal file
View file

@ -32,6 +32,7 @@
#include <QLayout> #include <QLayout>
#include <QString> #include <QString>
#include <QSlider> #include <QSlider>
#include <QDial>
#include <QSizePolicy> #include <QSizePolicy>
#include <QHostAddress> #include <QHostAddress>
#include "global.h" #include "global.h"
@ -58,12 +59,16 @@ public:
void SetGUIDesign ( const EGUIDesign eNewDesign ); void SetGUIDesign ( const EGUIDesign eNewDesign );
void SetDisplayChannelLevel ( const bool eNDCL ); void SetDisplayChannelLevel ( const bool eNDCL );
bool GetDisplayChannelLevel(); bool GetDisplayChannelLevel();
void SetDisplayPans ( const bool eNDP );
void UpdateSoloState ( const bool bNewOtherSoloState ); void UpdateSoloState ( const bool bNewOtherSoloState );
void SetFaderLevel ( const int iLevel ); void SetFaderLevel ( const int iLevel );
void SetPanValue ( const int iPan );
void SetFaderIsSolo ( const bool bIsSolo ); void SetFaderIsSolo ( const bool bIsSolo );
void SetFaderIsMute ( const bool bIsMute ); void SetFaderIsMute ( const bool bIsMute );
void SetRemoteFaderIsMute ( const bool bIsMute );
int GetFaderLevel() { return pFader->value(); } int GetFaderLevel() { return pFader->value(); }
int GetPanValue() { return pPan->value(); }
void Reset(); void Reset();
void SetChannelLevel ( const uint16_t iLevel ); void SetChannelLevel ( const uint16_t iLevel );
@ -71,6 +76,7 @@ protected:
double CalcFaderGain ( const int value ); double CalcFaderGain ( const int value );
void SetMute ( const bool bState ); void SetMute ( const bool bState );
void SendFaderLevelToServer ( const int iLevel ); void SendFaderLevelToServer ( const int iLevel );
void SendPanValueToServer ( const int iPan );
void SetupFaderTag ( const ESkillLevel eSkillLevel ); void SetupFaderTag ( const ESkillLevel eSkillLevel );
QFrame* pFrame; QFrame* pFrame;
@ -79,6 +85,9 @@ protected:
QWidget* pMuteSoloBox; QWidget* pMuteSoloBox;
CMultiColorLEDBar* plbrChannelLevel; CMultiColorLEDBar* plbrChannelLevel;
QSlider* pFader; QSlider* pFader;
QDial* pPan;
QLabel* pPanLabel;
QLabel* pInfoLabel;
QCheckBox* pcbMute; QCheckBox* pcbMute;
QCheckBox* pcbSolo; QCheckBox* pcbSolo;
@ -94,10 +103,12 @@ protected:
public slots: public slots:
void OnLevelValueChanged ( int value ) { SendFaderLevelToServer ( value ); } void OnLevelValueChanged ( int value ) { SendFaderLevelToServer ( value ); }
void OnPanValueChanged ( int value ) { SendPanValueToServer ( value ); }
void OnMuteStateChanged ( int value ); void OnMuteStateChanged ( int value );
signals: signals:
void gainValueChanged ( double value ); void gainValueChanged ( double value );
void panValueChanged ( double value );
void soloStateChanged ( int value ); void soloStateChanged ( int value );
}; };
@ -106,10 +117,13 @@ class CAudioMixerBoardSlots : public CAudioMixerBoardSlots<slotId - 1>
{ {
public: public:
void OnChGainValueChanged ( double dValue ) { UpdateGainValue ( slotId - 1, dValue ); } void OnChGainValueChanged ( double dValue ) { UpdateGainValue ( slotId - 1, dValue ); }
void OnChPanValueChanged ( double dValue ) { UpdatePanValue ( slotId - 1, dValue ); }
protected: protected:
virtual void UpdateGainValue ( const int iChannelIdx, virtual void UpdateGainValue ( const int iChannelIdx,
const double dValue ) = 0; const double dValue ) = 0;
virtual void UpdatePanValue ( const int iChannelIdx,
const double dValue ) = 0;
}; };
template<> template<>
@ -117,7 +131,7 @@ class CAudioMixerBoardSlots<0> {};
class CAudioMixerBoard : class CAudioMixerBoard :
public QScrollArea, public QGroupBox,
public CAudioMixerBoardSlots<MAX_NUM_CHANNELS> public CAudioMixerBoardSlots<MAX_NUM_CHANNELS>
{ {
Q_OBJECT Q_OBJECT
@ -130,6 +144,8 @@ public:
void SetServerName ( const QString& strNewServerName ); void SetServerName ( const QString& strNewServerName );
void SetGUIDesign ( const EGUIDesign eNewDesign ); void SetGUIDesign ( const EGUIDesign eNewDesign );
void SetDisplayChannelLevels ( const bool eNDCL ); void SetDisplayChannelLevels ( const bool eNDCL );
void SetPanIsSupported();
void SetRemoteFaderIsMute ( const int iChannelIdx, const bool bIsMute );
void SetFaderLevel ( const int iChannelIdx, void SetFaderLevel ( const int iChannelIdx,
const int iValue ); const int iValue );
@ -139,21 +155,41 @@ public:
// settings // settings
CVector<QString> vecStoredFaderTags; CVector<QString> vecStoredFaderTags;
CVector<int> vecStoredFaderLevels; CVector<int> vecStoredFaderLevels;
CVector<int> vecStoredPanValues;
CVector<int> vecStoredFaderIsSolo; CVector<int> vecStoredFaderIsSolo;
CVector<int> vecStoredFaderIsMute; CVector<int> vecStoredFaderIsMute;
int iNewClientFaderLevel; int iNewClientFaderLevel;
protected: protected:
class CMixerBoardScrollArea : public QScrollArea
{
public:
CMixerBoardScrollArea ( QWidget* parent = nullptr ) : QScrollArea ( parent ) {}
protected:
virtual void resizeEvent ( QResizeEvent* event )
{
// if after a resize of the main window a vertical scroll bar is required, make
// sure that the fader label is visible (scroll down completely)
ensureVisible ( 0, 2000 ); // use a large value here
QScrollArea::resizeEvent ( event );
}
};
bool GetStoredFaderSettings ( const CChannelInfo& ChanInfo, bool GetStoredFaderSettings ( const CChannelInfo& ChanInfo,
int& iStoredFaderLevel, int& iStoredFaderLevel,
int& iStoredPanValue,
bool& bStoredFaderIsSolo, bool& bStoredFaderIsSolo,
bool& bStoredFaderIsMute ); bool& bStoredFaderIsMute );
void StoreFaderSettings ( CChannelFader* pChanFader ); void StoreFaderSettings ( CChannelFader* pChanFader );
void UpdateSoloStates(); void UpdateSoloStates();
void OnGainValueChanged ( const int iChannelIdx,
const double dValue );
CVector<CChannelFader*> vecpChanFader; CVector<CChannelFader*> vecpChanFader;
QGroupBox* pGroupBox; CMixerBoardScrollArea* pScrollArea;
QHBoxLayout* pMainLayout; QHBoxLayout* pMainLayout;
bool bDisplayChannelLevels; bool bDisplayChannelLevels;
bool bNoFaderVisible; bool bNoFaderVisible;
@ -161,11 +197,14 @@ protected:
virtual void UpdateGainValue ( const int iChannelIdx, virtual void UpdateGainValue ( const int iChannelIdx,
const double dValue ); const double dValue );
virtual void UpdatePanValue ( const int iChannelIdx,
const double dValue );
template<unsigned int slotId> template<unsigned int slotId>
inline void connectFaderSignalsToMixerBoardSlots(); inline void connectFaderSignalsToMixerBoardSlots();
signals: signals:
void ChangeChanGain ( int iId, double dGain ); void ChangeChanGain ( int iId, double dGain );
void ChangeChanPan ( int iId, double dPan );
void NumClientsChanged ( int iNewNumClients ); void NumClientsChanged ( int iNewNumClients );
}; };

View file

@ -28,6 +28,7 @@
// CChannel implementation ***************************************************** // CChannel implementation *****************************************************
CChannel::CChannel ( const bool bNIsServer ) : CChannel::CChannel ( const bool bNIsServer ) :
vecdGains ( MAX_NUM_CHANNELS, 1.0 ), vecdGains ( MAX_NUM_CHANNELS, 1.0 ),
vecdPannings ( MAX_NUM_CHANNELS, 0.5 ),
bDoAutoSockBufSize ( true ), bDoAutoSockBufSize ( true ),
iFadeInCnt ( 0 ), iFadeInCnt ( 0 ),
iFadeInCntMax ( FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE ), iFadeInCntMax ( FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE ),
@ -86,6 +87,13 @@ qRegisterMetaType<CHostAddress> ( "CHostAddress" );
QObject::connect ( &Protocol, SIGNAL ( ChangeChanGain ( int, double ) ), QObject::connect ( &Protocol, SIGNAL ( ChangeChanGain ( int, double ) ),
this, SLOT ( OnChangeChanGain ( int, double ) ) ); this, SLOT ( OnChangeChanGain ( int, double ) ) );
QObject::connect ( &Protocol, SIGNAL ( ChangeChanPan ( int, double ) ),
this, SLOT ( OnChangeChanPan ( int, double ) ) );
QObject::connect ( &Protocol,
SIGNAL ( MuteStateHasChangedReceived ( int, bool ) ),
SIGNAL ( MuteStateHasChangedReceived ( int, bool ) ) );
QObject::connect ( &Protocol, SIGNAL ( ChangeChanInfo ( CChannelCoreInfo ) ), QObject::connect ( &Protocol, SIGNAL ( ChangeChanInfo ( CChannelCoreInfo ) ),
this, SLOT ( OnChangeChanInfo ( CChannelCoreInfo ) ) ); this, SLOT ( OnChangeChanInfo ( CChannelCoreInfo ) ) );
@ -105,6 +113,10 @@ qRegisterMetaType<CHostAddress> ( "CHostAddress" );
SIGNAL ( LicenceRequired ( ELicenceType ) ), SIGNAL ( LicenceRequired ( ELicenceType ) ),
SIGNAL ( LicenceRequired ( ELicenceType ) ) ); SIGNAL ( LicenceRequired ( ELicenceType ) ) );
QObject::connect ( &Protocol,
SIGNAL ( VersionAndOSReceived ( COSUtil::EOpSystemType, QString ) ),
SIGNAL ( VersionAndOSReceived ( COSUtil::EOpSystemType, QString ) ) );
QObject::connect ( &Protocol, QObject::connect ( &Protocol,
SIGNAL ( ReqChannelLevelList ( bool ) ), SIGNAL ( ReqChannelLevelList ( bool ) ),
this, SLOT ( OnReqChannelLevelList ( bool ) ) ); this, SLOT ( OnReqChannelLevelList ( bool ) ) );
@ -250,6 +262,16 @@ void CChannel::SetGain ( const int iChanID,
// set value (make sure channel ID is in range) // set value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) ) if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
{ {
// signal mute change
if ( ( vecdGains[iChanID] == 0 ) && ( dNewGain > 0 ) )
{
emit MuteStateHasChanged ( iChanID, false );
}
if ( ( vecdGains[iChanID] > 0 ) && ( dNewGain == 0 ) )
{
emit MuteStateHasChanged ( iChanID, true );
}
vecdGains[iChanID] = dNewGain; vecdGains[iChanID] = dNewGain;
} }
} }
@ -269,6 +291,33 @@ double CChannel::GetGain ( const int iChanID )
} }
} }
void CChannel::SetPan ( const int iChanID,
const double dNewPan )
{
QMutexLocker locker ( &Mutex );
// set value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
{
vecdPannings[iChanID] = dNewPan;
}
}
double CChannel::GetPan ( const int iChanID )
{
QMutexLocker locker ( &Mutex );
// get value (make sure channel ID is in range)
if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
{
return vecdPannings[iChanID];
}
else
{
return 0;
}
}
void CChannel::SetChanInfo ( const CChannelCoreInfo& NChanInf ) void CChannel::SetChanInfo ( const CChannelCoreInfo& NChanInf )
{ {
// apply value (if different from previous one) // apply value (if different from previous one)
@ -335,6 +384,12 @@ void CChannel::OnChangeChanGain ( int iChanID,
SetGain ( iChanID, dNewGain ); SetGain ( iChanID, dNewGain );
} }
void CChannel::OnChangeChanPan ( int iChanID,
double dNewPan )
{
SetPan ( iChanID, dNewPan );
}
void CChannel::OnChangeChanInfo ( CChannelCoreInfo ChanInfo ) void CChannel::OnChangeChanInfo ( CChannelCoreInfo ChanInfo )
{ {
SetChanInfo ( ChanInfo ); SetChanInfo ( ChanInfo );

View file

@ -105,14 +105,22 @@ public:
{ Protocol.CreateChanInfoMes ( ChInfo ); } { Protocol.CreateChanInfoMes ( ChInfo ); }
void CreateReqChanInfoMes() { Protocol.CreateReqChanInfoMes(); } void CreateReqChanInfoMes() { Protocol.CreateReqChanInfoMes(); }
void CreateVersionAndOSMes() { Protocol.CreateVersionAndOSMes(); }
void CreateMuteStateHasChangedMes ( const int iChanID, const bool bIsMuted ) { Protocol.CreateMuteStateHasChangedMes ( iChanID, bIsMuted ); }
void SetGain ( const int iChanID, const double dNewGain ); void SetGain ( const int iChanID, const double dNewGain );
double GetGain ( const int iChanID ); double GetGain ( const int iChanID );
double GetFadeInGain() { return static_cast<double> ( iFadeInCnt ) / iFadeInCntMax; } double GetFadeInGain() { return static_cast<double> ( iFadeInCnt ) / iFadeInCntMax; }
void SetPan ( const int iChanID, const double dNewPan );
double GetPan ( const int iChanID );
void SetRemoteChanGain ( const int iId, const double dGain ) void SetRemoteChanGain ( const int iId, const double dGain )
{ Protocol.CreateChanGainMes ( iId, dGain ); } { Protocol.CreateChanGainMes ( iId, dGain ); }
void SetRemoteChanPan ( const int iId, const double dPan )
{ Protocol.CreateChanPanMes ( iId, dPan ); }
bool SetSockBufNumFrames ( const int iNewNumFrames, bool SetSockBufNumFrames ( const int iNewNumFrames,
const bool bPreserve = false ); const bool bPreserve = false );
int GetSockBufNumFrames() const { return iCurSockBufNumFrames; } int GetSockBufNumFrames() const { return iCurSockBufNumFrames; }
@ -190,6 +198,7 @@ protected:
// mixer and effect settings // mixer and effect settings
CVector<double> vecdGains; CVector<double> vecdGains;
CVector<double> vecdPannings;
// network jitter-buffer // network jitter-buffer
CNetBufWithStats SockBuf; CNetBufWithStats SockBuf;
@ -228,6 +237,7 @@ public slots:
void OnSendProtMessage ( CVector<uint8_t> vecMessage ); void OnSendProtMessage ( CVector<uint8_t> vecMessage );
void OnJittBufSizeChange ( int iNewJitBufSize ); void OnJittBufSizeChange ( int iNewJitBufSize );
void OnChangeChanGain ( int iChanID, double dNewGain ); void OnChangeChanGain ( int iChanID, double dNewGain );
void OnChangeChanPan ( int iChanID, double dNewPan );
void OnChangeChanInfo ( CChannelCoreInfo ChanInfo ); void OnChangeChanInfo ( CChannelCoreInfo ChanInfo );
void OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps ); void OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps );
void OnReqNetTranspProps(); void OnReqNetTranspProps();
@ -268,10 +278,13 @@ signals:
void ReqConnClientsList(); void ReqConnClientsList();
void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo ); void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
void ChanInfoHasChanged(); void ChanInfoHasChanged();
void MuteStateHasChanged ( int iChanID, bool bIsMuted );
void MuteStateHasChangedReceived ( int iChanID, bool bIsMuted );
void ReqChanInfo(); void ReqChanInfo();
void ChatTextReceived ( QString strChatText ); void ChatTextReceived ( QString strChatText );
void ReqNetTranspProps(); void ReqNetTranspProps();
void LicenceRequired ( ELicenceType eLicenceType ); void LicenceRequired ( ELicenceType eLicenceType );
void VersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion );
void Disconnected(); void Disconnected();
void DetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData, void DetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData,

View file

@ -35,6 +35,7 @@ CClient::CClient ( const quint16 iPortNumber,
ChannelInfo (), ChannelInfo (),
vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ), vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ),
vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ), vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ),
vecStoredPanValues ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_PAN_MAX / 2 ),
vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ),
vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ), vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ),
iNewClientFaderLevel ( 100 ), iNewClientFaderLevel ( 100 ),
@ -78,7 +79,8 @@ CClient::CClient ( const quint16 iPortNumber,
bJitterBufferOK ( true ), bJitterBufferOK ( true ),
strCentralServerAddress ( "" ), strCentralServerAddress ( "" ),
eCentralServerAddressType ( AT_DEFAULT ), eCentralServerAddressType ( AT_DEFAULT ),
iServerSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ) iServerSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ),
pSignalHandler ( CSignalHandler::getSingletonP() )
{ {
int iOpusError; int iOpusError;
@ -155,10 +157,18 @@ CClient::CClient ( const quint16 iPortNumber,
SIGNAL ( ChatTextReceived ( QString ) ), SIGNAL ( ChatTextReceived ( QString ) ),
SIGNAL ( ChatTextReceived ( QString ) ) ); SIGNAL ( ChatTextReceived ( QString ) ) );
QObject::connect ( &Channel,
SIGNAL ( MuteStateHasChangedReceived ( int, bool ) ),
SIGNAL ( MuteStateHasChangedReceived ( int, bool ) ) );
QObject::connect ( &Channel, QObject::connect ( &Channel,
SIGNAL ( LicenceRequired ( ELicenceType ) ), SIGNAL ( LicenceRequired ( ELicenceType ) ),
SIGNAL ( LicenceRequired ( ELicenceType ) ) ); SIGNAL ( LicenceRequired ( ELicenceType ) ) );
QObject::connect ( &Channel,
SIGNAL ( VersionAndOSReceived ( COSUtil::EOpSystemType, QString ) ),
SIGNAL ( VersionAndOSReceived ( COSUtil::EOpSystemType, QString ) ) );
QObject::connect ( &ConnLessProtocol, QObject::connect ( &ConnLessProtocol,
SIGNAL ( CLMessReadyForSending ( CHostAddress, CVector<uint8_t> ) ), SIGNAL ( CLMessReadyForSending ( CHostAddress, CVector<uint8_t> ) ),
this, SLOT ( OnSendCLProtMessage ( CHostAddress, CVector<uint8_t> ) ) ); this, SLOT ( OnSendCLProtMessage ( CHostAddress, CVector<uint8_t> ) ) );
@ -204,6 +214,10 @@ CClient::CClient ( const quint16 iPortNumber,
QObject::connect ( &Socket, SIGNAL ( InvalidPacketReceived ( CHostAddress ) ), QObject::connect ( &Socket, SIGNAL ( InvalidPacketReceived ( CHostAddress ) ),
this, SLOT ( OnInvalidPacketReceived ( CHostAddress ) ) ); this, SLOT ( OnInvalidPacketReceived ( CHostAddress ) ) );
QObject::connect ( pSignalHandler,
SIGNAL ( HandledSignal ( int ) ),
this, SLOT ( OnHandledSignal ( int ) ) );
// start the socket (it is important to start the socket after all // start the socket (it is important to start the socket after all
// initializations and connections) // initializations and connections)
@ -647,6 +661,27 @@ void CClient::OnCLChannelLevelListReceived ( CHostAddress InetAddr,
emit CLChannelLevelListReceived ( InetAddr, vecLevelList ); emit CLChannelLevelListReceived ( InetAddr, vecLevelList );
} }
void CClient::OnHandledSignal ( int sigNum )
{
#ifdef _WIN32
// Windows does not actually get OnHandledSignal triggered
QCoreApplication::instance()->exit();
Q_UNUSED ( sigNum )
#else
switch ( sigNum )
{
case SIGINT:
case SIGTERM:
// This should trigger OnAboutToQuit
QCoreApplication::instance()->exit();
break;
default:
break;
}
#endif
}
void CClient::Start() void CClient::Start()
{ {
// init object // init object
@ -836,7 +871,6 @@ void CClient::Init()
vecCeltData.Init ( iCeltNumCodedBytes ); vecCeltData.Init ( iCeltNumCodedBytes );
vecZeros.Init ( iStereoBlockSizeSam, 0 ); vecZeros.Init ( iStereoBlockSizeSam, 0 );
vecsStereoSndCrdTMP.Init ( iStereoBlockSizeSam );
vecsStereoSndCrdMuteStream.Init ( iStereoBlockSizeSam ); vecsStereoSndCrdMuteStream.Init ( iStereoBlockSizeSam );
opus_custom_encoder_ctl ( CurOpusEncoder, opus_custom_encoder_ctl ( CurOpusEncoder,
@ -894,30 +928,13 @@ JitterMeas.Measure();
*/ */
} }
void CClient::ProcessSndCrdAudioData ( CVector<int16_t>& vecsMultChanAudioSndCrd ) void CClient::ProcessSndCrdAudioData ( CVector<int16_t>& vecsStereoSndCrd )
{ {
// TODO output mapping from stereo to multi channel: We want to change all the different sound interfaces that they
// do not select the input and output channels but we do it here at the client. This has the advantage that, e.g.,
// the special add modes supported for Windows (i.e. if 4 input channels available, you can mix channel 1+3 or 1+4)
// can then be used for Mac as well without the need of changing anything in the actual Mac sound interface.
// Since a multichannel signal arrives and must be converted to a stereo signal, we need an additional buffer: vecsStereoSndCrdTMP.
// TEST input channel selection/mixing
//const int iNumInCh = 2;
//for ( int i = 0; i < iNumInCh; i++ )
//{
// for ( int j = 0; j < iMonoBlockSizeSam; j++ )
// {
// vecsStereoSndCrdTMP[2 * j + i] = vecsMultChanAudioSndCrd[iNumInCh * j + i];
// }
//}
vecsStereoSndCrdTMP = vecsMultChanAudioSndCrd; // TEST just copy the stereo data for now
// check if a conversion buffer is required or not // check if a conversion buffer is required or not
if ( bSndCrdConversionBufferRequired ) if ( bSndCrdConversionBufferRequired )
{ {
// add new sound card block in conversion buffer // add new sound card block in conversion buffer
SndCrdConversionBufferIn.Put ( vecsStereoSndCrdTMP, vecsStereoSndCrdTMP.Size() ); SndCrdConversionBufferIn.Put ( vecsStereoSndCrd, vecsStereoSndCrd.Size() );
// process all available blocks of data // process all available blocks of data
while ( SndCrdConversionBufferIn.GetAvailData() >= iStereoBlockSizeSam ) while ( SndCrdConversionBufferIn.GetAvailData() >= iStereoBlockSizeSam )
@ -932,17 +949,14 @@ vecsStereoSndCrdTMP = vecsMultChanAudioSndCrd; // TEST just copy the stereo data
} }
// get processed sound card block out of the conversion buffer // get processed sound card block out of the conversion buffer
SndCrdConversionBufferOut.Get ( vecsStereoSndCrdTMP, vecsStereoSndCrdTMP.Size() ); SndCrdConversionBufferOut.Get ( vecsStereoSndCrd, vecsStereoSndCrd.Size() );
} }
else else
{ {
// regular case: no conversion buffer required // regular case: no conversion buffer required
// process audio data // process audio data
ProcessAudioDataIntern ( vecsStereoSndCrdTMP ); ProcessAudioDataIntern ( vecsStereoSndCrd );
} }
// TODO output mapping from stereo to multi channel, see comment above for the input mapping
vecsMultChanAudioSndCrd = vecsStereoSndCrdTMP; // TEST just copy the stereo data for now
} }
void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd ) void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )

View file

@ -39,6 +39,7 @@
#include "channel.h" #include "channel.h"
#include "util.h" #include "util.h"
#include "buffer.h" #include "buffer.h"
#include "signalhandler.h"
#ifdef LLCON_VST_PLUGIN #ifdef LLCON_VST_PLUGIN
# include "vstsound.h" # include "vstsound.h"
#else #else
@ -245,6 +246,9 @@ public:
void SetRemoteChanGain ( const int iId, const double dGain ) void SetRemoteChanGain ( const int iId, const double dGain )
{ Channel.SetRemoteChanGain ( iId, dGain ); } { Channel.SetRemoteChanGain ( iId, dGain ); }
void SetRemoteChanPan ( const int iId, const double dPan )
{ Channel.SetRemoteChanPan ( iId, dPan ); }
void SetRemoteInfo() { Channel.SetRemoteInfo ( ChannelInfo ); } void SetRemoteInfo() { Channel.SetRemoteInfo ( ChannelInfo ); }
void CreateChatTextMes ( const QString& strChatText ) void CreateChatTextMes ( const QString& strChatText )
@ -279,6 +283,7 @@ public:
CChannelCoreInfo ChannelInfo; CChannelCoreInfo ChannelInfo;
CVector<QString> vecStoredFaderTags; CVector<QString> vecStoredFaderTags;
CVector<int> vecStoredFaderLevels; CVector<int> vecStoredFaderLevels;
CVector<int> vecStoredPanValues;
CVector<int> vecStoredFaderIsSolo; CVector<int> vecStoredFaderIsSolo;
CVector<int> vecStoredFaderIsMute; CVector<int> vecStoredFaderIsMute;
int iNewClientFaderLevel; int iNewClientFaderLevel;
@ -306,7 +311,7 @@ protected:
static void AudioCallback ( CVector<short>& psData, void* arg ); static void AudioCallback ( CVector<short>& psData, void* arg );
void Init(); void Init();
void ProcessSndCrdAudioData ( CVector<short>& vecsMultChanAudioSndCrd ); void ProcessSndCrdAudioData ( CVector<short>& vecsStereoSndCrd );
void ProcessAudioDataIntern ( CVector<short>& vecsStereoSndCrd ); void ProcessAudioDataIntern ( CVector<short>& vecsStereoSndCrd );
int PreparePingMessage(); int PreparePingMessage();
@ -360,7 +365,6 @@ protected:
CBufferBase<int16_t> SndCrdConversionBufferIn; CBufferBase<int16_t> SndCrdConversionBufferIn;
CBufferBase<int16_t> SndCrdConversionBufferOut; CBufferBase<int16_t> SndCrdConversionBufferOut;
CVector<int16_t> vecDataConvBuf; CVector<int16_t> vecDataConvBuf;
CVector<int16_t> vecsStereoSndCrdTMP;
CVector<int16_t> vecsStereoSndCrdMuteStream; CVector<int16_t> vecsStereoSndCrdMuteStream;
CVector<int16_t> vecZeros; CVector<int16_t> vecZeros;
@ -386,7 +390,10 @@ protected:
// for ping measurement // for ping measurement
CPreciseTime PreciseTime; CPreciseTime PreciseTime;
CSignalHandler* pSignalHandler;
public slots: public slots:
void OnHandledSignal ( int sigNum );
void OnSendProtMessage ( CVector<uint8_t> vecMessage ); void OnSendProtMessage ( CVector<uint8_t> vecMessage );
void OnInvalidPacketReceived ( CHostAddress RecHostAddr ); void OnInvalidPacketReceived ( CHostAddress RecHostAddr );
@ -417,7 +424,9 @@ public slots:
signals: signals:
void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo ); void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
void ChatTextReceived ( QString strChatText ); void ChatTextReceived ( QString strChatText );
void MuteStateHasChangedReceived ( int iChanID, bool bIsMuted );
void LicenceRequired ( ELicenceType eLicenceType ); void LicenceRequired ( ELicenceType eLicenceType );
void VersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion );
void PingTimeReceived ( int iPingTime ); void PingTimeReceived ( int iPingTime );
void CLServerListReceived ( CHostAddress InetAddr, void CLServerListReceived ( CHostAddress InetAddr,

View file

@ -39,7 +39,7 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
bConnectDlgWasShown ( false ), bConnectDlgWasShown ( false ),
ClientSettingsDlg ( pNCliP, parent, Qt::Window ), ClientSettingsDlg ( pNCliP, parent, Qt::Window ),
ChatDlg ( parent, Qt::Window ), ChatDlg ( parent, Qt::Window ),
ConnectDlg ( bNewShowComplRegConnList, parent, Qt::Dialog ), ConnectDlg ( pNCliP, bNewShowComplRegConnList, parent, Qt::Dialog ),
AnalyzerConsole ( pNCliP, parent, Qt::Window ), AnalyzerConsole ( pNCliP, parent, Qt::Window ),
MusicianProfileDlg ( pNCliP, parent ) MusicianProfileDlg ( pNCliP, parent )
{ {
@ -85,7 +85,7 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
// connect/disconnect button // connect/disconnect button
butConnect->setWhatsThis ( "<b>" + tr ( "Connect/Disconnect Button" ) + ":</b> " + butConnect->setWhatsThis ( "<b>" + tr ( "Connect/Disconnect Button" ) + ":</b> " +
tr ( "Push this button to connect a server. A dialog where you can " tr ( "Push this button to connect to a server. A dialog where you can "
"select a server will open. If you are connected, pressing this " "select a server will open. If you are connected, pressing this "
"button will end the session." ) ); "button will end the session." ) );
@ -123,7 +123,7 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
"sound card and a reverberation effect shall be applied, set the " "sound card and a reverberation effect shall be applied, set the "
"channel selector to right and move the fader upwards until the " "channel selector to right and move the fader upwards until the "
"desired reverberation level is reached." ) + "<br>" + tr ( "desired reverberation level is reached." ) + "<br>" + tr (
"The reverberation effect requires significant CPU so that it should " "The reverberation effect requires significant CPU so it should "
"only be used on fast PCs. If the reverberation level fader is set to " "only be used on fast PCs. If the reverberation level fader is set to "
"minimum (which is the default setting), the reverberation effect is " "minimum (which is the default setting), the reverberation effect is "
"switched off and does not cause any additional CPU usage." ); "switched off and does not cause any additional CPU usage." );
@ -169,7 +169,7 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
"<ul>" "<ul>"
"<li>" + tr ( "The network jitter buffer is not large enough for the current " "<li>" + tr ( "The network jitter buffer is not large enough for the current "
"network/audio interface jitter." ) + "</li>" "network/audio interface jitter." ) + "</li>"
"<li>" + tr ( "The sound card buffer delay (buffer size) is set to a too small " "<li>" + tr ( "The sound card buffer delay (buffer size) is set to too small a "
"value." ) + "</li>" "value." ) + "</li>"
"<li>" + tr ( "The upload or download stream rate is too high for the current " "<li>" + tr ( "The upload or download stream rate is too high for the current "
"available internet bandwidth." ) + "</li>" "available internet bandwidth." ) + "</li>"
@ -193,6 +193,7 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
// restore fader settings // restore fader settings
MainMixerBoard->vecStoredFaderTags = pClient->vecStoredFaderTags; MainMixerBoard->vecStoredFaderTags = pClient->vecStoredFaderTags;
MainMixerBoard->vecStoredFaderLevels = pClient->vecStoredFaderLevels; MainMixerBoard->vecStoredFaderLevels = pClient->vecStoredFaderLevels;
MainMixerBoard->vecStoredPanValues = pClient->vecStoredPanValues;
MainMixerBoard->vecStoredFaderIsSolo = pClient->vecStoredFaderIsSolo; MainMixerBoard->vecStoredFaderIsSolo = pClient->vecStoredFaderIsSolo;
MainMixerBoard->vecStoredFaderIsMute = pClient->vecStoredFaderIsMute; MainMixerBoard->vecStoredFaderIsMute = pClient->vecStoredFaderIsMute;
MainMixerBoard->iNewClientFaderLevel = pClient->iNewClientFaderLevel; MainMixerBoard->iNewClientFaderLevel = pClient->iNewClientFaderLevel;
@ -465,6 +466,10 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
SIGNAL ( ChatTextReceived ( QString ) ), SIGNAL ( ChatTextReceived ( QString ) ),
this, SLOT ( OnChatTextReceived ( QString ) ) ); this, SLOT ( OnChatTextReceived ( QString ) ) );
QObject::connect ( pClient,
SIGNAL ( MuteStateHasChangedReceived ( int, bool ) ),
this, SLOT ( OnMuteStateHasChangedReceived ( int, bool ) ) );
// This connection is a special case. On receiving a licence required message via the // This connection is a special case. On receiving a licence required message via the
// protocol, a modal licence dialog is opened. Since this blocks the thread, we need // protocol, a modal licence dialog is opened. Since this blocks the thread, we need
// a queued connection to make sure the core protocol mechanism is not blocked, too. // a queued connection to make sure the core protocol mechanism is not blocked, too.
@ -497,6 +502,10 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
SIGNAL ( CLChannelLevelListReceived ( CHostAddress, CVector<uint16_t> ) ), SIGNAL ( CLChannelLevelListReceived ( CHostAddress, CVector<uint16_t> ) ),
this, SLOT ( OnCLChannelLevelListReceived ( CHostAddress, CVector<uint16_t> ) ) ); this, SLOT ( OnCLChannelLevelListReceived ( CHostAddress, CVector<uint16_t> ) ) );
QObject::connect ( pClient,
SIGNAL ( VersionAndOSReceived ( COSUtil::EOpSystemType, QString ) ),
this, SLOT ( OnVersionAndOSReceived ( COSUtil::EOpSystemType, QString ) ) );
#ifdef ENABLE_CLIENT_VERSION_AND_OS_DEBUGGING #ifdef ENABLE_CLIENT_VERSION_AND_OS_DEBUGGING
QObject::connect ( pClient, QObject::connect ( pClient,
SIGNAL ( CLVersionAndOSReceived ( CHostAddress, COSUtil::EOpSystemType, QString ) ), SIGNAL ( CLVersionAndOSReceived ( CHostAddress, COSUtil::EOpSystemType, QString ) ),
@ -521,6 +530,9 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ), QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ),
this, SLOT ( OnChangeChanGain ( int, double ) ) ); this, SLOT ( OnChangeChanGain ( int, double ) ) );
QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanPan ( int, double ) ),
this, SLOT ( OnChangeChanPan ( int, double ) ) );
QObject::connect ( MainMixerBoard, SIGNAL ( NumClientsChanged ( int ) ), QObject::connect ( MainMixerBoard, SIGNAL ( NumClientsChanged ( int ) ),
this, SLOT ( OnNumClientsChanged ( int ) ) ); this, SLOT ( OnNumClientsChanged ( int ) ) );
@ -585,6 +597,7 @@ void CClientDlg::closeEvent ( QCloseEvent* Event )
MainMixerBoard->HideAll(); MainMixerBoard->HideAll();
pClient->vecStoredFaderTags = MainMixerBoard->vecStoredFaderTags; pClient->vecStoredFaderTags = MainMixerBoard->vecStoredFaderTags;
pClient->vecStoredFaderLevels = MainMixerBoard->vecStoredFaderLevels; pClient->vecStoredFaderLevels = MainMixerBoard->vecStoredFaderLevels;
pClient->vecStoredPanValues = MainMixerBoard->vecStoredPanValues;
pClient->vecStoredFaderIsSolo = MainMixerBoard->vecStoredFaderIsSolo; pClient->vecStoredFaderIsSolo = MainMixerBoard->vecStoredFaderIsSolo;
pClient->vecStoredFaderIsMute = MainMixerBoard->vecStoredFaderIsMute; pClient->vecStoredFaderIsMute = MainMixerBoard->vecStoredFaderIsMute;
pClient->iNewClientFaderLevel = MainMixerBoard->iNewClientFaderLevel; pClient->iNewClientFaderLevel = MainMixerBoard->iNewClientFaderLevel;
@ -700,7 +713,7 @@ void CClientDlg::OnConnectDlgAccepted()
if ( strSelectedAddress.isEmpty() ) if ( strSelectedAddress.isEmpty() )
{ {
strSelectedAddress = DEFAULT_SERVER_ADDRESS; strSelectedAddress = DEFAULT_SERVER_ADDRESS;
strMixerBoardLabel = DEFAULT_SERVER_NAME; strMixerBoardLabel = tr ( "Central Server" );
} }
} }
@ -744,6 +757,18 @@ void CClientDlg::OnCentralServerAddressTypeChanged()
} }
} }
void CClientDlg::OnVersionAndOSReceived ( COSUtil::EOpSystemType ,
QString strVersion )
{
// check if Pan is supported by the server (minimum version is 3.5.4)
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 5, 4 ) ) >= 0 )
{
MainMixerBoard->SetPanIsSupported();
}
#endif
}
void CClientDlg::OnChatTextReceived ( QString strChatText ) void CClientDlg::OnChatTextReceived ( QString strChatText )
{ {
ChatDlg.AddChatText ( strChatText ); ChatDlg.AddChatText ( strChatText );
@ -1150,6 +1175,7 @@ void CClientDlg::SetGUIDesign ( const EGUIDesign eNewDesign )
"QRadioButton { color: rgb(220, 220, 220);" "QRadioButton { color: rgb(220, 220, 220);"
" font: bold; }" " font: bold; }"
"QScrollArea { background: transparent; }" "QScrollArea { background: transparent; }"
".QWidget { background: transparent; }" // note: matches instances of QWidget, but not of its subclasses
"QGroupBox { background: transparent; }" "QGroupBox { background: transparent; }"
"QGroupBox::title { color: rgb(220, 220, 220); }" "QGroupBox::title { color: rgb(220, 220, 220); }"
"QCheckBox::indicator { width: 38px;" "QCheckBox::indicator { width: 38px;"

View file

@ -33,6 +33,9 @@
#include <QRadioButton> #include <QRadioButton>
#include <QMenuBar> #include <QMenuBar>
#include <QLayout> #include <QLayout>
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
# include <QVersionNumber>
#endif
#include "global.h" #include "global.h"
#include "client.h" #include "client.h"
#include "settings.h" #include "settings.h"
@ -131,6 +134,9 @@ public slots:
const int iValue ) { MainMixerBoard->SetFaderLevel ( iChannelIdx, const int iValue ) { MainMixerBoard->SetFaderLevel ( iChannelIdx,
iValue ); } iValue ); }
void OnVersionAndOSReceived ( COSUtil::EOpSystemType ,
QString strVersion );
#ifdef ENABLE_CLIENT_VERSION_AND_OS_DEBUGGING #ifdef ENABLE_CLIENT_VERSION_AND_OS_DEBUGGING
void OnCLVersionAndOSReceived ( CHostAddress InetAddr, void OnCLVersionAndOSReceived ( CHostAddress InetAddr,
COSUtil::EOpSystemType eOSType, COSUtil::EOpSystemType eOSType,
@ -166,6 +172,9 @@ public slots:
void OnChangeChanGain ( int iId, double dGain ) void OnChangeChanGain ( int iId, double dGain )
{ pClient->SetRemoteChanGain ( iId, dGain ); } { pClient->SetRemoteChanGain ( iId, dGain ); }
void OnChangeChanPan ( int iId, double dPan )
{ pClient->SetRemoteChanPan ( iId, dPan ); }
void OnNewLocalInputText ( QString strChatText ) void OnNewLocalInputText ( QString strChatText )
{ pClient->CreateChatTextMes ( strChatText ); } { pClient->CreateChatTextMes ( strChatText ); }
@ -189,6 +198,9 @@ public slots:
CVector<CChannelInfo> vecChanInfo ) CVector<CChannelInfo> vecChanInfo )
{ ConnectDlg.SetConnClientsList ( InetAddr, vecChanInfo ); } { ConnectDlg.SetConnClientsList ( InetAddr, vecChanInfo ); }
void OnMuteStateHasChangedReceived ( int iChanID, bool bIsMuted )
{ MainMixerBoard->SetRemoteFaderIsMute ( iChanID, bIsMuted ); }
void OnCLChannelLevelListReceived ( CHostAddress /* unused */, void OnCLChannelLevelListReceived ( CHostAddress /* unused */,
CVector<uint16_t> vecLevelList ) CVector<uint16_t> vecLevelList )
{ MainMixerBoard->SetChannelLevels ( vecLevelList ); } { MainMixerBoard->SetChannelLevels ( vecLevelList ); }

View file

@ -41,8 +41,8 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
"(the longer the buffer, the higher the delay)." ) + "<br>" + tr ( "(the longer the buffer, the higher the delay)." ) + "<br>" + tr (
"The jitter buffer size can be manually chosen for the local client " "The jitter buffer size can be manually chosen for the local client "
"and the remote server. For the local jitter buffer, dropouts in the " "and the remote server. For the local jitter buffer, dropouts in the "
"audio stream are indicated by the light on the bottom " "audio stream are indicated by the light below the"
"of the jitter buffer size faders. If the light turns to red, a buffer " "jitter buffer size faders. If the light turns to red, a buffer "
"overrun/underrun took place and the audio stream is interrupted." ) + "<br>" + tr ( "overrun/underrun took place and the audio stream is interrupted." ) + "<br>" + tr (
"The jitter buffer setting is therefore a trade-off between audio " "The jitter buffer setting is therefore a trade-off between audio "
"quality and overall delay." ) + "<br>" + tr ( "quality and overall delay." ) + "<br>" + tr (
@ -61,7 +61,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
"functionality and to lower the jitter buffer size manually by " "functionality and to lower the jitter buffer size manually by "
"using the sliders until your personal acceptable limit of the amount " "using the sliders until your personal acceptable limit of the amount "
"of dropouts is reached. The LED indicator will visualize the audio " "of dropouts is reached. The LED indicator will visualize the audio "
"dropouts of the local jitter buffer by a red light." ) + "dropouts of the local jitter buffer with a red light." ) +
TOOLTIP_COM_END_TEXT; TOOLTIP_COM_END_TEXT;
lblNetBuf->setWhatsThis ( strJitterBufferSize ); lblNetBuf->setWhatsThis ( strJitterBufferSize );
@ -93,7 +93,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
#ifdef _WIN32 #ifdef _WIN32
// set Windows specific tool tip // set Windows specific tool tip
cbxSoundcard->setToolTip ( tr ( "In case the ASIO4ALL driver is used, " cbxSoundcard->setToolTip ( tr ( "If the ASIO4ALL driver is used, "
"please note that this driver usually introduces approx. 10-30 ms of " "please note that this driver usually introduces approx. 10-30 ms of "
"additional audio delay. Using a sound card with a native ASIO driver " "additional audio delay. Using a sound card with a native ASIO driver "
"is therefore recommended." ) + "<br>" + tr ( "If you are using the kX ASIO " "is therefore recommended." ) + "<br>" + tr ( "If you are using the kX ASIO "
@ -126,7 +126,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
"If enabled, the support for very small network audio packets is activated. Very small " "If enabled, the support for very small network audio packets is activated. Very small "
"network packets are only actually used if the sound card buffer delay is smaller than " ) + "network packets are only actually used if the sound card buffer delay is smaller than " ) +
QString().setNum ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ) + tr ( " samples. The " QString().setNum ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ) + tr ( " samples. The "
"smaller the network buffers, the smaller the audio latency. But at the same time " "smaller the network buffers, the lower the audio latency. But at the same time "
"the network load increases and the probability of audio dropouts also increases." ) ); "the network load increases and the probability of audio dropouts also increases." ) );
chbEnableOPUS64->setAccessibleName ( tr ( "Enable small network buffers check box" ) ); chbEnableOPUS64->setAccessibleName ( tr ( "Enable small network buffers check box" ) );
@ -138,14 +138,14 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
"connection properties." ) + "<br>" + tr ( "connection properties." ) + "<br>" + tr (
"Three buffer sizes are supported" ) + "Three buffer sizes are supported" ) +
":<ul>" ":<ul>"
"<li>" + tr ( "64 samples: This is the preferred setting since it gives lowest " "<li>" + tr ( "64 samples: This is the preferred setting since it provides the lowest "
"latency but does not work with all sound cards." ) + "</li>" "latency but does not work with all sound cards." ) + "</li>"
"<li>" + tr ( "128 samples: This setting should work on most of the available " "<li>" + tr ( "128 samples: This setting should work for most available "
"sound cards." ) + "</li>" "sound cards." ) + "</li>"
"<li>" + tr ( "256 samples: This setting should only be used if only a very slow " "<li>" + tr ( "256 samples: This setting should only be used if only a very slow "
"computer or a slow internet connection is available." ) + "</li>" "computer or a slow internet connection is available." ) + "</li>"
"</ul>" + tr ( "</ul>" + tr (
"Some sound card driver do not allow the buffer delay to be changed " "Some sound card drivers do not allow the buffer delay to be changed "
"from within the " ) + APP_NAME + "from within the " ) + APP_NAME +
tr ( " software. In this case the buffer delay setting " tr ( " software. In this case the buffer delay setting "
"is disabled. To change the actual buffer delay, this " "is disabled. To change the actual buffer delay, this "
@ -158,7 +158,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
"performance." ) + "<br>" + tr ( "performance." ) + "<br>" + tr (
"The actual buffer delay has influence on the connection status, the " "The actual buffer delay has influence on the connection status, the "
"current upload rate and the overall delay. The lower the buffer size, " "current upload rate and the overall delay. The lower the buffer size, "
"the higher the probability of red light in the status indicator (drop " "the higher the probability of a red light in the status indicator (drop "
"outs) and the higher the upload rate and the lower the overall " "outs) and the higher the upload rate and the lower the overall "
"delay." ) + "<br>" + tr ( "delay." ) + "<br>" + tr (
"The buffer setting is therefore a trade-off between audio " "The buffer setting is therefore a trade-off between audio "
@ -172,13 +172,13 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
"change the buffer size." ) + TOOLTIP_COM_END_TEXT; "change the buffer size." ) + TOOLTIP_COM_END_TEXT;
rbtBufferDelayPreferred->setWhatsThis ( strSndCrdBufDelay ); rbtBufferDelayPreferred->setWhatsThis ( strSndCrdBufDelay );
rbtBufferDelayPreferred->setAccessibleName ( tr ( "128 samples setting radio button" ) ); rbtBufferDelayPreferred->setAccessibleName ( tr ( "64 samples setting radio button" ) );
rbtBufferDelayPreferred->setToolTip ( strSndCrdBufDelayTT ); rbtBufferDelayPreferred->setToolTip ( strSndCrdBufDelayTT );
rbtBufferDelayDefault->setWhatsThis ( strSndCrdBufDelay ); rbtBufferDelayDefault->setWhatsThis ( strSndCrdBufDelay );
rbtBufferDelayDefault->setAccessibleName ( tr ( "256 samples setting radio button" ) ); rbtBufferDelayDefault->setAccessibleName ( tr ( "128 samples setting radio button" ) );
rbtBufferDelayDefault->setToolTip ( strSndCrdBufDelayTT ); rbtBufferDelayDefault->setToolTip ( strSndCrdBufDelayTT );
rbtBufferDelaySafe->setWhatsThis ( strSndCrdBufDelay ); rbtBufferDelaySafe->setWhatsThis ( strSndCrdBufDelay );
rbtBufferDelaySafe->setAccessibleName ( tr ( "512 samples setting radio button" ) ); rbtBufferDelaySafe->setAccessibleName ( tr ( "256 samples setting radio button" ) );
rbtBufferDelaySafe->setToolTip ( strSndCrdBufDelayTT ); rbtBufferDelaySafe->setToolTip ( strSndCrdBufDelayTT );
butDriverSetup->setWhatsThis ( strSndCrdBufDelay ); butDriverSetup->setWhatsThis ( strSndCrdBufDelay );
butDriverSetup->setAccessibleName ( tr ( "ASIO setup push button" ) ); butDriverSetup->setAccessibleName ( tr ( "ASIO setup push button" ) );
@ -200,10 +200,10 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
QString strAudioChannels = "<b>" + tr ( "Audio Channels" ) + ":</b> " + tr ( QString strAudioChannels = "<b>" + tr ( "Audio Channels" ) + ":</b> " + tr (
"Select the number of audio channels to be used. There are three " "Select the number of audio channels to be used. There are three "
"modes available. The mono and stereo modes use one and two " "modes available. The mono and stereo modes use one and two "
"audio channels respectively. In the mono-in/stereo-out mode " "audio channels respectively. In mono-in/stereo-out mode "
"the audio signal which is sent to the server is mono but the " "the audio signal which is sent to the server is mono but the "
"return signal is stereo. This is useful for the case that the " "return signal is stereo. This is useful if the "
"sound card puts the instrument on one input channel and the " "sound card has the instrument on one input channel and the "
"microphone on the other channel. In that case the two input signals " "microphone on the other channel. In that case the two input signals "
"can be mixed to one mono channel but the server mix can be heard in " "can be mixed to one mono channel but the server mix can be heard in "
"stereo." ) + "<br>" + tr ( "stereo." ) + "<br>" + tr (
@ -259,7 +259,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
// current connection status parameter // current connection status parameter
QString strConnStats = "<b>" + tr ( "Current Connection Status " QString strConnStats = "<b>" + tr ( "Current Connection Status "
"Parameter" ) + ":</b> " + tr ( "The ping time is the time required for the audio " "Parameter" ) + ":</b> " + tr ( "The ping time is the time required for the audio "
"stream to travel from the client to the server and backwards. This " "stream to travel from the client to the server and back again. This "
"delay is introduced by the network. This delay should be as low as " "delay is introduced by the network. This delay should be as low as "
"20-30 ms. If this delay is higher (e.g., 50-60 ms), your distance to " "20-30 ms. If this delay is higher (e.g., 50-60 ms), your distance to "
"the server is too large or your internet connection is not " "the server is too large or your internet connection is not "
@ -346,9 +346,11 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
// central server address type combo box // central server address type combo box
cbxCentServAddrType->clear(); cbxCentServAddrType->clear();
cbxCentServAddrType->addItem ( tr ( "Manual" ) ); // AT_MANUAL cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_CUSTOM ) );
cbxCentServAddrType->addItem ( tr ( "Default" ) ); // AT_DEFAULT cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_DEFAULT ) );
cbxCentServAddrType->addItem ( tr ( "Default (North America)" ) ); // AT_NORTH_AMERICA cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENERAL_NORTHAMERICA ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENRE_ROCK ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENRE_JAZZ ) );
cbxCentServAddrType->setCurrentIndex ( static_cast<int> ( pClient->GetCentralServerAddressType() ) ); cbxCentServAddrType->setCurrentIndex ( static_cast<int> ( pClient->GetCentralServerAddressType() ) );
UpdateCentralServerDependency(); UpdateCentralServerDependency();
@ -443,6 +445,10 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, QWidget* parent,
SIGNAL ( buttonClicked ( QAbstractButton* ) ), this, SIGNAL ( buttonClicked ( QAbstractButton* ) ), this,
SLOT ( OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* ) ) ); SLOT ( OnSndCrdBufferDelayButtonGroupClicked ( QAbstractButton* ) ) );
QObject::connect ( pClient,
SIGNAL ( CentralServerAddressTypeChanged() ),
this, SLOT ( OnCentralServerAddressTypeChanged() ) );
// Timers ------------------------------------------------------------------ // Timers ------------------------------------------------------------------
// start timer for status bar // start timer for status bar
@ -581,7 +587,14 @@ void CClientSettingsDlg::UpdateSoundChannelSelectionFrame()
void CClientSettingsDlg::UpdateCentralServerDependency() void CClientSettingsDlg::UpdateCentralServerDependency()
{ {
const bool bCurUseDefCentServAddr = ( pClient->GetCentralServerAddressType() != AT_MANUAL ); const bool bCurUseDefCentServAddr = ( pClient->GetCentralServerAddressType() != AT_CUSTOM );
// update server type combo box (because the value may have ben changed
// by a control in another dialog, e.g., the connect dialog),
// since it is just an update, do not fire signals for the update
cbxCentServAddrType->blockSignals ( true );
cbxCentServAddrType->setCurrentIndex ( static_cast<int> ( pClient->GetCentralServerAddressType() ) );
cbxCentServAddrType->blockSignals ( false );
// make sure the line edit does not fire signals when we update the text // make sure the line edit does not fire signals when we update the text
edtCentralServerAddress->blockSignals ( true ); edtCentralServerAddress->blockSignals ( true );
@ -590,7 +603,7 @@ void CClientSettingsDlg::UpdateCentralServerDependency()
{ {
// if the default central server is used, just show a text of the // if the default central server is used, just show a text of the
// server name // server name
edtCentralServerAddress->setText ( DEFAULT_SERVER_NAME ); edtCentralServerAddress->setText ( tr ( "Predefined Address" ) );
} }
else else
{ {

View file

@ -102,6 +102,7 @@ protected:
void OnAudioChannelsActivated ( int iChanIdx ); void OnAudioChannelsActivated ( int iChanIdx );
void OnAudioQualityActivated ( int iQualityIdx ); void OnAudioQualityActivated ( int iQualityIdx );
void OnCentServAddrTypeActivated ( int iTypeIdx ); void OnCentServAddrTypeActivated ( int iTypeIdx );
void OnCentralServerAddressTypeChanged() { UpdateCentralServerDependency(); }
void OnDriverSetupClicked(); void OnDriverSetupClicked();
signals: signals:

View file

@ -26,10 +26,12 @@
/* Implementation *************************************************************/ /* Implementation *************************************************************/
CConnectDlg::CConnectDlg ( const bool bNewShowCompleteRegList, CConnectDlg::CConnectDlg ( CClient* pNCliP,
const bool bNewShowCompleteRegList,
QWidget* parent, QWidget* parent,
Qt::WindowFlags f ) Qt::WindowFlags f )
: QDialog ( parent, f ), : QDialog ( parent, f ),
pClient ( pNCliP ),
strCentralServerAddress ( "" ), strCentralServerAddress ( "" ),
strSelectedAddress ( "" ), strSelectedAddress ( "" ),
strSelectedServerName ( "" ), strSelectedServerName ( "" ),
@ -74,6 +76,14 @@ CConnectDlg::CConnectDlg ( const bool bNewShowCompleteRegList,
cbxServerAddr->setAccessibleDescription ( tr ( "Holds the current server " cbxServerAddr->setAccessibleDescription ( tr ( "Holds the current server "
"IP address or URL. It also stores old URLs in the combo box list." ) ); "IP address or URL. It also stores old URLs in the combo box list." ) );
// central server address type combo box
cbxCentServAddrType->clear();
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_CUSTOM ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_DEFAULT ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENERAL_NORTHAMERICA ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENRE_ROCK ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENRE_JAZZ ) );
// filter // filter
edtFilter->setWhatsThis ( "<b>" + tr ( "Filter" ) + ":</b> " + tr ( "The server " edtFilter->setWhatsThis ( "<b>" + tr ( "Filter" ) + ":</b> " + tr ( "The server "
"list is filtered by the given text. Note that the filter is case insensitive." ) ); "list is filtered by the given text. Note that the filter is case insensitive." ) );
@ -162,6 +172,9 @@ CConnectDlg::CConnectDlg ( const bool bNewShowCompleteRegList,
QObject::connect ( cbxServerAddr, SIGNAL ( editTextChanged ( const QString& ) ), QObject::connect ( cbxServerAddr, SIGNAL ( editTextChanged ( const QString& ) ),
this, SLOT ( OnServerAddrEditTextChanged ( const QString& ) ) ); this, SLOT ( OnServerAddrEditTextChanged ( const QString& ) ) );
QObject::connect ( cbxCentServAddrType, SIGNAL ( activated ( int ) ),
this, SLOT ( OnCentServAddrTypeChanged ( int ) ) );
// check boxes // check boxes
QObject::connect ( chbExpandAll, SIGNAL ( stateChanged ( int ) ), QObject::connect ( chbExpandAll, SIGNAL ( stateChanged ( int ) ),
this, SLOT ( OnExpandAllStateChanged ( int ) ) ); this, SLOT ( OnExpandAllStateChanged ( int ) ) );
@ -220,6 +233,11 @@ void CConnectDlg::RequestServerList()
// clear filter edit box // clear filter edit box
edtFilter->setText ( "" ); edtFilter->setText ( "" );
// update list combo box (disable events to avoid a signal)
cbxCentServAddrType->blockSignals ( true );
cbxCentServAddrType->setCurrentIndex ( static_cast<int> ( pClient->GetCentralServerAddressType() ) );
cbxCentServAddrType->blockSignals ( false );
// get the IP address of the central server (using the ParseNetworAddress // get the IP address of the central server (using the ParseNetworAddress
// function) when the connect dialog is opened, this seems to be the correct // function) when the connect dialog is opened, this seems to be the correct
// time to do it // time to do it

View file

@ -47,7 +47,8 @@ class CConnectDlg : public QDialog, private Ui_CConnectDlgBase
Q_OBJECT Q_OBJECT
public: public:
CConnectDlg ( const bool bNewShowCompleteRegList, CConnectDlg ( CClient* pNCliP,
const bool bNewShowCompleteRegList,
QWidget* parent = nullptr, QWidget* parent = nullptr,
Qt::WindowFlags f = nullptr ); Qt::WindowFlags f = nullptr );
@ -88,6 +89,8 @@ protected:
void UpdateListFilter(); void UpdateListFilter();
void ShowAllMusicians ( const bool bState ); void ShowAllMusicians ( const bool bState );
CClient* pClient;
QTimer TimerPing; QTimer TimerPing;
QTimer TimerReRequestServList; QTimer TimerReRequestServList;
QString strCentralServerAddress; QString strCentralServerAddress;
@ -104,6 +107,7 @@ public slots:
void OnServerListItemSelectionChanged(); void OnServerListItemSelectionChanged();
void OnServerListItemDoubleClicked ( QTreeWidgetItem* Item, int ); void OnServerListItemDoubleClicked ( QTreeWidgetItem* Item, int );
void OnServerAddrEditTextChanged ( const QString& ); void OnServerAddrEditTextChanged ( const QString& );
void OnCentServAddrTypeChanged ( int iTypeIdx ) { pClient->SetCentralServerAddressType ( static_cast<ECSAddType> ( iTypeIdx ) ); }
void OnFilterTextEdited ( const QString& ) { UpdateListFilter(); } void OnFilterTextEdited ( const QString& ) { UpdateListFilter(); }
void OnExpandAllStateChanged ( int value ) { ShowAllMusicians ( value == Qt::Checked ); } void OnExpandAllStateChanged ( int value ) { ShowAllMusicians ( value == Qt::Checked ); }
void OnConnectClicked(); void OnConnectClicked();

View file

@ -29,6 +29,16 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item>
<widget class="QLabel" name="lblList">
<property name="text">
<string>List</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbxCentServAddrType"/>
</item>
<item> <item>
<widget class="QLabel" name="lblFilter"> <widget class="QLabel" name="lblFilter">
<property name="text"> <property name="text">

View file

@ -101,12 +101,15 @@ LED bar: lbr
#define SYSTEM_FRAME_SIZE_SAMPLES 64 #define SYSTEM_FRAME_SIZE_SAMPLES 64
#define DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ( 2 * SYSTEM_FRAME_SIZE_SAMPLES ) #define DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ( 2 * SYSTEM_FRAME_SIZE_SAMPLES )
// default server address // default server address and port numbers
#define DEFAULT_SERVER_ADDRESS "jamulus.fischvolk.de" #define DEFAULT_SERVER_ADDRESS "jamulus.fischvolk.de"
#define DEFAULT_SERVER_NAME "Central Server" #define DEFAULT_PORT_NUMBER 22124
#define CENTSERV_GENERAL_NORTHAMERICA "jamulus.fischvolk.de:22224"
#define CENTSERV_GENRE_ROCK "centralrock.drealm.info:22124"
#define CENTSERV_GENRE_JAZZ "centraljazz.drealm.info:22224"
// getting started and software manual URL // getting started and software manual URL
#define CLIENT_GETTING_STARTED_URL "https://github.com/corrados/jamulus/wiki/Software-Manual" #define CLIENT_GETTING_STARTED_URL "https://github.com/corrados/jamulus/wiki/Getting-Started"
#define SERVER_GETTING_STARTED_URL "https://github.com/corrados/jamulus/wiki/Running-a-Server" #define SERVER_GETTING_STARTED_URL "https://github.com/corrados/jamulus/wiki/Running-a-Server"
#define SOFTWARE_MANUAL_URL "https://github.com/corrados/jamulus/blob/master/src/res/homepage/manual.md" #define SOFTWARE_MANUAL_URL "https://github.com/corrados/jamulus/blob/master/src/res/homepage/manual.md"
@ -116,10 +119,6 @@ LED bar: lbr
#define WELL_KNOWN_PORT 53 // DNS #define WELL_KNOWN_PORT 53 // DNS
#define IP_LOOKUP_TIMEOUT 500 // ms #define IP_LOOKUP_TIMEOUT 500 // ms
// defined port numbers for client and server
#define DEFAULT_PORT_NUMBER 22124
#define DEFAULT_PORT_NUMBER_NORTHAMERICA 22224
// system sample rate (the sound card and audio coder works on this sample rate) // system sample rate (the sound card and audio coder works on this sample rate)
#define SYSTEM_SAMPLE_RATE_HZ 48000 // Hz #define SYSTEM_SAMPLE_RATE_HZ 48000 // Hz
@ -148,8 +147,9 @@ LED bar: lbr
// default network buffer size // default network buffer size
#define DEF_NET_BUF_SIZE_NUM_BL 10 // number of blocks #define DEF_NET_BUF_SIZE_NUM_BL 10 // number of blocks
// audio mixer fader maximum value // audio mixer fader and panning maximum value
#define AUD_MIX_FADER_MAX 100 #define AUD_MIX_FADER_MAX 100
#define AUD_MIX_PAN_MAX 100
// maximum number of recognized sound cards installed in the system, // maximum number of recognized sound cards installed in the system,
// definition for "no device" // definition for "no device"
@ -163,10 +163,10 @@ LED bar: lbr
#define MAX_NUM_IN_OUT_CHANNELS 64 #define MAX_NUM_IN_OUT_CHANNELS 64
// maximum number of elemts in the server address combo box // maximum number of elemts in the server address combo box
#define MAX_NUM_SERVER_ADDR_ITEMS 6 #define MAX_NUM_SERVER_ADDR_ITEMS 12
// maximum number of fader settings to be stored (together with the fader tags) // maximum number of fader settings to be stored (together with the fader tags)
#define MAX_NUM_STORED_FADER_SETTINGS 200 #define MAX_NUM_STORED_FADER_SETTINGS 250
// range for signal level meter // range for signal level meter
#define LOW_BOUND_SIG_METER ( -50.0 ) // dB #define LOW_BOUND_SIG_METER ( -50.0 ) // dB
@ -182,21 +182,20 @@ LED bar: lbr
// Maximum number of servers registered in the server list. If you want to // Maximum number of servers registered in the server list. If you want to
// change this parameter, you most probably have to adjust MAX_SIZE_BYTES_NETW_BUF. // change this parameter, you most probably have to adjust MAX_SIZE_BYTES_NETW_BUF.
#define MAX_NUM_SERVERS_IN_SERVER_LIST 200 #define MAX_NUM_SERVERS_IN_SERVER_LIST 150 // reduced to 150 because we now have genre-based server lists
// defines the time interval at which the ping time is updated in the GUI // defines the time interval at which the ping time is updated in the GUI
#define PING_UPDATE_TIME_MS 500 // ms #define PING_UPDATE_TIME_MS 500 // ms
// defines the time interval at which the ping time is updated for the server // defines the time interval at which the ping time is updated for the server list
// list #define PING_UPDATE_TIME_SERVER_LIST_MS 2500 // ms
#define PING_UPDATE_TIME_SERVER_LIST_MS 2000 // ms
// defines the interval between Channel Level updates from the server // defines the interval between Channel Level updates from the server
#define CHANNEL_LEVEL_UPDATE_INTERVAL 200 // number of frames at 64 samples frame size #define CHANNEL_LEVEL_UPDATE_INTERVAL 200 // number of frames at 64 samples frame size
// time-out until a registered server is deleted from the server list if no // time-out until a registered server is deleted from the server list if no
// new registering was made in minutes // new registering was made in minutes
#define SERVLIST_TIME_OUT_MINUTES 60 // minutes #define SERVLIST_TIME_OUT_MINUTES 33 // minutes (should include 3 UDP registration messages)
// poll time for server list (to check if entries are time-out) // poll time for server list (to check if entries are time-out)
#define SERVLIST_POLL_TIME_MINUTES 1 // minute #define SERVLIST_POLL_TIME_MINUTES 1 // minute
@ -208,7 +207,7 @@ LED bar: lbr
#define SERVLIST_REGIST_INTERV_MINUTES 15 // minutes #define SERVLIST_REGIST_INTERV_MINUTES 15 // minutes
// defines the minimum time a server must run to be a permanent server // defines the minimum time a server must run to be a permanent server
#define SERVLIST_TIME_PERMSERV_MINUTES 1440 // minutes, 1440 = 60 min * 24 h #define SERVLIST_TIME_PERMSERV_MINUTES 4320 // minutes, 4320 = 60 min * 24 h * 3 d
// registration response timeout // registration response timeout
#define REGISTER_SERVER_TIME_OUT_MS 500 // ms #define REGISTER_SERVER_TIME_OUT_MS 500 // ms

View file

@ -64,6 +64,20 @@ MESSAGES (with connection)
+-------------------+--------------+ +-------------------+--------------+
- PROTMESSID_CHANNEL_PAN: Gain of channel
+-------------------+-----------------+
| 1 byte channel ID | 2 bytes panning |
+-------------------+-----------------+
- PROTMESSID_MUTE_STATE_CHANGED: Mute state of your signal at another client has changed
+-------------------+-----------------+
| 1 byte channel ID | 1 byte is muted |
+-------------------+-----------------+
- PROTMESSID_CONN_CLIENTS_LIST: Information about connected clients - PROTMESSID_CONN_CLIENTS_LIST: Information about connected clients
for each connected client append following data: for each connected client append following data:
@ -154,7 +168,7 @@ MESSAGES (with connection)
| 1 byte licence type | | 1 byte licence type |
+---------------------+ +---------------------+
- PROTMESSID_CLM_REQ_CHANNEL_LEVEL_LIST: Opt in or out of the channel level list - PROTMESSID_REQ_CHANNEL_LEVEL_LIST: Opt in or out of the channel level list
+---------------+ +---------------+
| 1 byte option | | 1 byte option |
@ -162,6 +176,12 @@ MESSAGES (with connection)
option is boolean, true to opt in, false to opt out option is boolean, true to opt in, false to opt out
- PROTMESSID_VERSION_AND_OS: Version number and operating system
+-------------------------+------------------+------------------------------+
| 1 byte operating system | 2 bytes number n | n bytes UTF-8 string version |
+-------------------------+------------------+------------------------------+
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### // #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
- PROTMESSID_OPUS_SUPPORTED: Informs that OPUS codec is supported - PROTMESSID_OPUS_SUPPORTED: Informs that OPUS codec is supported
@ -573,6 +593,14 @@ if ( rand() < ( RAND_MAX / 2 ) ) return false;
bRet = EvaluateChanGainMes ( vecbyMesBodyData ); bRet = EvaluateChanGainMes ( vecbyMesBodyData );
break; break;
case PROTMESSID_CHANNEL_PAN:
bRet = EvaluateChanPanMes ( vecbyMesBodyData );
break;
case PROTMESSID_MUTE_STATE_CHANGED:
bRet = EvaluateMuteStateHasChangedMes ( vecbyMesBodyData );
break;
case PROTMESSID_CONN_CLIENTS_LIST: case PROTMESSID_CONN_CLIENTS_LIST:
bRet = EvaluateConClientListMes ( vecbyMesBodyData ); bRet = EvaluateConClientListMes ( vecbyMesBodyData );
break; break;
@ -608,6 +636,10 @@ if ( rand() < ( RAND_MAX / 2 ) ) return false;
case PROTMESSID_REQ_CHANNEL_LEVEL_LIST: case PROTMESSID_REQ_CHANNEL_LEVEL_LIST:
bRet = EvaluateReqChannelLevelListMes ( vecbyMesBodyData ); bRet = EvaluateReqChannelLevelListMes ( vecbyMesBodyData );
break; break;
case PROTMESSID_VERSION_AND_OS:
bRet = EvaluateVersionAndOSMes ( vecbyMesBodyData );
break;
} }
// immediately send acknowledge message // immediately send acknowledge message
@ -795,12 +827,10 @@ bool CProtocol::EvaluateChanGainMes ( const CVector<uint8_t>& vecData )
} }
// channel ID // channel ID
const int iCurID = const int iCurID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
// gain (read integer value) // gain (read integer value)
const int iData = const int iData = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
// we convert the gain from integer to double with range 0..1 // we convert the gain from integer to double with range 0..1
const double dNewGain = static_cast<double> ( iData ) / ( 1 << 15 ); const double dNewGain = static_cast<double> ( iData ) / ( 1 << 15 );
@ -811,6 +841,85 @@ bool CProtocol::EvaluateChanGainMes ( const CVector<uint8_t>& vecData )
return false; // no error return false; // no error
} }
void CProtocol::CreateChanPanMes ( const int iChanID, const double dPan )
{
CVector<uint8_t> vecData ( 3 ); // 3 bytes of data
int iPos = 0; // init position pointer
// build data vector
// channel ID
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iChanID ), 1 );
// actual gain, we convert from double with range 0..1 to integer
const int iCurPan = static_cast<int> ( dPan * ( 1 << 15 ) );
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iCurPan ), 2 );
CreateAndSendMessage ( PROTMESSID_CHANNEL_PAN, vecData );
}
bool CProtocol::EvaluateChanPanMes ( const CVector<uint8_t> &vecData )
{
int iPos = 0; // init position pointer
// check size
if ( vecData.Size() != 3 )
{
return true; // return error code
}
// channel ID
const int iCurID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
// pan (read integer value)
const int iData = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
// we convert the gain from integer to double with range 0..1
const double dNewPan = static_cast<double> ( iData ) / ( 1 << 15 );
// invoke message action
emit ChangeChanPan ( iCurID, dNewPan );
return false; // no error
}
void CProtocol::CreateMuteStateHasChangedMes ( const int iChanID, const bool bIsMuted )
{
CVector<uint8_t> vecData ( 2 ); // 2 bytes of data
int iPos = 0; // init position pointer
// build data vector
// channel ID
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iChanID ), 1 );
// mute state
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( bIsMuted ), 1 );
CreateAndSendMessage ( PROTMESSID_MUTE_STATE_CHANGED, vecData );
}
bool CProtocol::EvaluateMuteStateHasChangedMes ( const CVector<uint8_t> &vecData )
{
int iPos = 0; // init position pointer
// check size
if ( vecData.Size() != 2 )
{
return true; // return error code
}
// channel ID
const int iCurID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
// mute state
const bool bIsMuted = static_cast<bool> ( GetValFromStream ( vecData, iPos, 1 ) );
// invoke message action
emit MuteStateHasChangedReceived ( iCurID, bIsMuted );
return false; // no error
}
void CProtocol::CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo ) void CProtocol::CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo )
{ {
const int iNumClients = vecChanInfo.Size(); const int iNumClients = vecChanInfo.Size();
@ -1335,6 +1444,71 @@ bool CProtocol::EvaluateReqChannelLevelListMes ( const CVector<uint8_t>& vecData
return false; // no error return false; // no error
} }
void CProtocol::CreateVersionAndOSMes()
{
int iPos = 0; // init position pointer
// get the version number string
const QString strVerion = VERSION;
// convert version string to utf-8
const QByteArray strUTF8Version = strVerion.toUtf8();
// size of current message body
const int iEntrLen =
1 /* operating system */ +
2 /* version utf-8 string size */ + strUTF8Version.size();
// build data vector
CVector<uint8_t> vecData ( iEntrLen );
// operating system (1 byte)
PutValOnStream ( vecData, iPos,
static_cast<uint32_t> ( COSUtil::GetOperatingSystem() ), 1 );
// version
PutStringUTF8OnStream ( vecData, iPos, strUTF8Version );
CreateAndSendMessage ( PROTMESSID_VERSION_AND_OS, vecData );
}
bool CProtocol::EvaluateVersionAndOSMes ( const CVector<uint8_t>& vecData )
{
int iPos = 0; // init position pointer
const int iDataLen = vecData.Size();
// check size (the first 1 byte)
if ( iDataLen < 1 )
{
return true; // return error code
}
// operating system (1 byte)
const COSUtil::EOpSystemType eOSType =
static_cast<COSUtil::EOpSystemType> ( GetValFromStream ( vecData, iPos, 1 ) );
// version text
QString strVersion;
if ( GetStringFromStream ( vecData,
iPos,
MAX_LEN_VERSION_TEXT,
strVersion ) )
{
return true; // return error code
}
// check size: all data is read, the position must now be at the end
if ( iPos != iDataLen )
{
return true; // return error code
}
// invoke message action
emit VersionAndOSReceived ( eOSType, strVersion );
return false; // no error
}
// Connection less messages ---------------------------------------------------- // Connection less messages ----------------------------------------------------
void CProtocol::CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs ) void CProtocol::CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs )

12
src/protocol.h Executable file → Normal file
View file

@ -55,6 +55,9 @@
#define PROTMESSID_OPUS_SUPPORTED 26 // tells that OPUS codec is supported #define PROTMESSID_OPUS_SUPPORTED 26 // tells that OPUS codec is supported
#define PROTMESSID_LICENCE_REQUIRED 27 // licence required #define PROTMESSID_LICENCE_REQUIRED 27 // licence required
#define PROTMESSID_REQ_CHANNEL_LEVEL_LIST 28 // request the channel level list #define PROTMESSID_REQ_CHANNEL_LEVEL_LIST 28 // request the channel level list
#define PROTMESSID_VERSION_AND_OS 29 // version number and operating system
#define PROTMESSID_CHANNEL_PAN 30 // set channel pan for mix
#define PROTMESSID_MUTE_STATE_CHANGED 31 // mute state of your signal at another client has changed
// message IDs of connection less messages (CLM) // message IDs of connection less messages (CLM)
// DEFINITION -> start at 1000, end at 1999, see IsConnectionLessMessageID // DEFINITION -> start at 1000, end at 1999, see IsConnectionLessMessageID
@ -96,6 +99,8 @@ public:
void CreateJitBufMes ( const int iJitBufSize ); void CreateJitBufMes ( const int iJitBufSize );
void CreateReqJitBufMes(); void CreateReqJitBufMes();
void CreateChanGainMes ( const int iChanID, const double dGain ); void CreateChanGainMes ( const int iChanID, const double dGain );
void CreateChanPanMes ( const int iChanID, const double dPan );
void CreateMuteStateHasChangedMes ( const int iChanID, const bool bIsMuted );
void CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo ); void CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo );
void CreateReqConnClientsList(); void CreateReqConnClientsList();
void CreateChanInfoMes ( const CChannelCoreInfo ChanInfo ); void CreateChanInfoMes ( const CChannelCoreInfo ChanInfo );
@ -106,6 +111,7 @@ public:
void CreateLicenceRequiredMes ( const ELicenceType eLicenceType ); void CreateLicenceRequiredMes ( const ELicenceType eLicenceType );
void CreateOpusSupportedMes(); void CreateOpusSupportedMes();
void CreateReqChannelLevelListMes ( const bool bRCL ); void CreateReqChannelLevelListMes ( const bool bRCL );
void CreateVersionAndOSMes();
void CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs ); void CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs );
void CreateCLPingWithNumClientsMes ( const CHostAddress& InetAddr, void CreateCLPingWithNumClientsMes ( const CHostAddress& InetAddr,
@ -218,6 +224,8 @@ protected:
bool EvaluateJitBufMes ( const CVector<uint8_t>& vecData ); bool EvaluateJitBufMes ( const CVector<uint8_t>& vecData );
bool EvaluateReqJitBufMes(); bool EvaluateReqJitBufMes();
bool EvaluateChanGainMes ( const CVector<uint8_t>& vecData ); bool EvaluateChanGainMes ( const CVector<uint8_t>& vecData );
bool EvaluateChanPanMes ( const CVector<uint8_t>& vecData );
bool EvaluateMuteStateHasChangedMes ( const CVector<uint8_t>& vecData );
bool EvaluateConClientListMes ( const CVector<uint8_t>& vecData ); bool EvaluateConClientListMes ( const CVector<uint8_t>& vecData );
bool EvaluateReqConnClientsList(); bool EvaluateReqConnClientsList();
bool EvaluateChanInfoMes ( const CVector<uint8_t>& vecData ); bool EvaluateChanInfoMes ( const CVector<uint8_t>& vecData );
@ -227,6 +235,7 @@ protected:
bool EvaluateReqNetwTranspPropsMes(); bool EvaluateReqNetwTranspPropsMes();
bool EvaluateLicenceRequiredMes ( const CVector<uint8_t>& vecData ); bool EvaluateLicenceRequiredMes ( const CVector<uint8_t>& vecData );
bool EvaluateReqChannelLevelListMes ( const CVector<uint8_t>& vecData ); bool EvaluateReqChannelLevelListMes ( const CVector<uint8_t>& vecData );
bool EvaluateVersionAndOSMes ( const CVector<uint8_t>& vecData );
bool EvaluateCLPingMes ( const CHostAddress& InetAddr, bool EvaluateCLPingMes ( const CHostAddress& InetAddr,
const CVector<uint8_t>& vecData ); const CVector<uint8_t>& vecData );
@ -276,6 +285,8 @@ signals:
void ReqJittBufSize(); void ReqJittBufSize();
void ChangeNetwBlSiFact ( int iNewNetwBlSiFact ); void ChangeNetwBlSiFact ( int iNewNetwBlSiFact );
void ChangeChanGain ( int iChanID, double dNewGain ); void ChangeChanGain ( int iChanID, double dNewGain );
void ChangeChanPan ( int iChanID, double dNewPan );
void MuteStateHasChangedReceived ( int iCurID, bool bIsMuted );
void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo ); void ConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
void ServerFullMesReceived(); void ServerFullMesReceived();
void ReqConnClientsList(); void ReqConnClientsList();
@ -286,6 +297,7 @@ signals:
void ReqNetTranspProps(); void ReqNetTranspProps();
void LicenceRequired ( ELicenceType eLicenceType ); void LicenceRequired ( ELicenceType eLicenceType );
void ReqChannelLevelList ( bool bOptIn ); void ReqChannelLevelList ( bool bOptIn );
void VersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion );
void CLPingReceived ( CHostAddress InetAddr, void CLPingReceived ( CHostAddress InetAddr,
int iMs ); int iMs );

View file

@ -314,6 +314,10 @@ void CJamRecorder::Init( const CServer* server,
throw std::runtime_error( (recordBaseDir.absolutePath() + " is a directory but cannot be written to").toStdString() ); throw std::runtime_error( (recordBaseDir.absolutePath() + " is a directory but cannot be written to").toStdString() );
} }
QObject::connect( (const QObject *)server, SIGNAL ( RestartRecorder() ),
this, SLOT( OnTriggerSession() ),
Qt::ConnectionType::QueuedConnection );
QObject::connect( (const QObject *)server, SIGNAL ( Stopped() ), QObject::connect( (const QObject *)server, SIGNAL ( Stopped() ),
this, SLOT( OnEnd() ), this, SLOT( OnEnd() ),
Qt::ConnectionType::QueuedConnection ); Qt::ConnectionType::QueuedConnection );
@ -322,13 +326,12 @@ void CJamRecorder::Init( const CServer* server,
this, SLOT( OnDisconnected ( int ) ), this, SLOT( OnDisconnected ( int ) ),
Qt::ConnectionType::QueuedConnection ); Qt::ConnectionType::QueuedConnection );
qRegisterMetaType<CVector<int16_t>>(); qRegisterMetaType<CVector<int16_t>> ( "CVector<int16_t>" );
QObject::connect( (const QObject *)server, SIGNAL ( AudioFrame( const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ), QObject::connect( (const QObject *)server, SIGNAL ( AudioFrame( const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ),
this, SLOT( OnFrame (const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ), this, SLOT( OnFrame (const int, const QString, const CHostAddress, const int, const CVector<int16_t> ) ),
Qt::ConnectionType::QueuedConnection ); Qt::ConnectionType::QueuedConnection );
QObject::connect( QCoreApplication::instance(), QObject::connect( QCoreApplication::instance(), SIGNAL ( aboutToQuit() ),
SIGNAL ( aboutToQuit() ),
this, SLOT( OnAboutToQuit() ) ); this, SLOT( OnAboutToQuit() ) );
iServerFrameSizeSamples = _iServerFrameSizeSamples; iServerFrameSizeSamples = _iServerFrameSizeSamples;
@ -338,11 +341,10 @@ void CJamRecorder::Init( const CServer* server,
thisThread->start(); thisThread->start();
} }
/** /**
* @brief CJamRecorder::OnStart Start up tasks when the first client connects * @brief CJamRecorder::Start Start up tasks for a new session
*/ */
void CJamRecorder::OnStart() { void CJamRecorder::Start() {
// Ensure any previous cleaning up has been done. // Ensure any previous cleaning up has been done.
OnEnd(); OnEnd();
@ -350,11 +352,17 @@ void CJamRecorder::OnStart() {
isRecording = true; isRecording = true;
} }
/** /**
* @brief CJamRecorder::OnEnd Finalise the recording and emit the Reaper RPP file * @brief CJamRecorder::OnEnd Finalise the recording and emit the Reaper RPP file
*
* Emits RecordingSessionEnded with the Reaper project file name,
* or null if was not recording or a problem occurs
*/ */
void CJamRecorder::OnEnd() void CJamRecorder::OnEnd()
{ {
QString reaperProjectFileName = QString::Null();
if ( isRecording ) if ( isRecording )
{ {
isRecording = false; isRecording = false;
@ -366,21 +374,46 @@ void CJamRecorder::OnEnd()
if (fi.exists()) if (fi.exists())
{ {
qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "exists and will not be overwritten."; qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "exists and will not be overwritten.";
reaperProjectFileName = QString::Null();
} }
else else
{ {
QFile outf (reaperProjectFileName); QFile outf (reaperProjectFileName);
outf.open(QFile::WriteOnly); if ( outf.open(QFile::WriteOnly) )
{
QTextStream out(&outf); QTextStream out(&outf);
out << CReaperProject( currentSession->Tracks(), iServerFrameSizeSamples ).toString() << endl; out << CReaperProject( currentSession->Tracks(), iServerFrameSizeSamples ).toString() << endl;
qDebug() << "Session RPP:" << reaperProjectFileName; qDebug() << "Session RPP:" << reaperProjectFileName;
} }
else
{
qWarning() << "CJamRecorder::OnEnd():" << fi.absolutePath() << "could not be created, no RPP written.";
reaperProjectFileName = QString::Null();
}
}
delete currentSession; delete currentSession;
currentSession = nullptr; currentSession = nullptr;
} }
emit RecordingSessionEnded ( reaperProjectFileName );
} }
/**
* @brief CJamRecorder::OnTriggerSession End one session and start a new one
*/
void CJamRecorder::OnTriggerSession()
{
// This should magically get everything right...
if ( isRecording )
{
Start();
}
}
/**
* @brief CJamRecorder::OnAboutToQuit End any recording and exit thread
*/
void CJamRecorder::OnAboutToQuit() void CJamRecorder::OnAboutToQuit()
{ {
OnEnd(); OnEnd();
@ -452,7 +485,7 @@ void CJamRecorder::OnFrame(const int iChID, const QString name, const CHostAddre
// Make sure we are ready // Make sure we are ready
if ( !isRecording ) if ( !isRecording )
{ {
OnStart(); Start();
} }
currentSession->Frame( iChID, name, address, numAudioChannels, data, iServerFrameSizeSamples ); currentSession->Frame( iChID, name, address, numAudioChannels, data, iServerFrameSizeSamples );

View file

@ -143,21 +143,44 @@ public:
{ {
} }
/**
* @brief Create recording directory, if necessary, and connect signal handlers
* @param server Server object emiting signals
*/
void Init( const CServer* server, const int _iServerFrameSizeSamples ); void Init( const CServer* server, const int _iServerFrameSizeSamples );
/**
* @brief SessionDirToReaper Method that allows an RPP file to be recreated
* @param strSessionDirName Where the session wave files are
* @param serverFrameSizeSamples What the server frame size was for the session
*/
static void SessionDirToReaper( QString& strSessionDirName, int serverFrameSizeSamples ); static void SessionDirToReaper( QString& strSessionDirName, int serverFrameSizeSamples );
public slots: private:
/** void Start();
* @brief Raised when first client joins the server, triggering a new recording.
*/
void OnStart();
QDir recordBaseDir;
bool isRecording;
CJamSession* currentSession;
int iServerFrameSizeSamples;
QThread* thisThread;
signals:
void RecordingSessionEnded ( QString sessionDir );
private slots:
/** /**
* @brief Raised when last client leaves the server, ending the recording. * @brief Raised when last client leaves the server, ending the recording.
*/ */
void OnEnd(); void OnEnd();
/**
* @brief Raised to end one session and start a new one.
*/
void OnTriggerSession();
/** /**
* @brief Raised when application is stopping * @brief Raised when application is stopping
*/ */
@ -173,15 +196,6 @@ public slots:
* @brief Raised when a frame of data is available to process * @brief Raised when a frame of data is available to process
*/ */
void OnFrame ( const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector<int16_t> data ); void OnFrame ( const int iChID, const QString name, const CHostAddress address, const int numAudioChannels, const CVector<int16_t> data );
private:
QDir recordBaseDir;
bool isRecording;
CJamSession* currentSession;
int iServerFrameSizeSamples;
QThread* thisThread;
}; };
} }

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

Before

Width:  |  Height:  |  Size: 931 B

After

Width:  |  Height:  |  Size: 931 B

View file

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 929 B

View file

Before

Width:  |  Height:  |  Size: 587 B

After

Width:  |  Height:  |  Size: 587 B

View file

Before

Width:  |  Height:  |  Size: 1,016 B

After

Width:  |  Height:  |  Size: 1,016 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 936 B

After

Width:  |  Height:  |  Size: 936 B

View file

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 955 B

After

Width:  |  Height:  |  Size: 955 B

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

Before

Width:  |  Height:  |  Size: 900 B

After

Width:  |  Height:  |  Size: 900 B

View file

Before

Width:  |  Height:  |  Size: 917 B

After

Width:  |  Height:  |  Size: 917 B

View file

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,9 @@
<qresource prefix="/translations" lang="nl"> <qresource prefix="/translations" lang="nl">
<file alias="translation.qm">res/translation/translation_nl_NL.qm</file> <file alias="translation.qm">res/translation/translation_nl_NL.qm</file>
</qresource> </qresource>
<qresource prefix="/translations" lang="it">
<file alias="translation.qm">res/translation/translation_it_IT.qm</file>
</qresource>
<qresource prefix="/png/LEDs"> <qresource prefix="/png/LEDs">
<file>res/CLEDDisabledSmall.png</file> <file>res/CLEDDisabledSmall.png</file>
<file>res/CLEDGreenArrow.png</file> <file>res/CLEDGreenArrow.png</file>
@ -36,34 +39,34 @@
<file>res/mixerboardbackground.png</file> <file>res/mixerboardbackground.png</file>
</qresource> </qresource>
<qresource prefix="/png/instr"> <qresource prefix="/png/instr">
<file>res/instruments/instrnone.png</file> <file>res/instruments/none.png</file>
<file>res/instruments/instrbassguitar.png</file> <file>res/instruments/bassguitar.png</file>
<file>res/instruments/instrclarinet.png</file> <file>res/instruments/clarinet.png</file>
<file>res/instruments/instrdrumset.png</file> <file>res/instruments/drumset.png</file>
<file>res/instruments/instreguitar.png</file> <file>res/instruments/eguitar.png</file>
<file>res/instruments/instrsaxophone.png</file> <file>res/instruments/saxophone.png</file>
<file>res/instruments/instrtrumpet.png</file> <file>res/instruments/trumpet.png</file>
<file>res/instruments/instrmicrophone.png</file> <file>res/instruments/microphone.png</file>
<file>res/instruments/instrkeyboard.png</file> <file>res/instruments/keyboard.png</file>
<file>res/instruments/instrviolin.png</file> <file>res/instruments/violin.png</file>
<file>res/instruments/instraguitar.png</file> <file>res/instruments/aguitar.png</file>
<file>res/instruments/instrflute.png</file> <file>res/instruments/flute.png</file>
<file>res/instruments/instraccordeon.png</file> <file>res/instruments/accordeon.png</file>
<file>res/instruments/instrcello.png</file> <file>res/instruments/cello.png</file>
<file>res/instruments/instrtrombone.png</file> <file>res/instruments/trombone.png</file>
<file>res/instruments/instrfrenchhorn.png</file> <file>res/instruments/frenchhorn.png</file>
<file>res/instruments/instrtuba.png</file> <file>res/instruments/tuba.png</file>
<file>res/instruments/instrdoublebass.png</file> <file>res/instruments/doublebass.png</file>
<file>res/instruments/instrgrandpiano.png</file> <file>res/instruments/grandpiano.png</file>
<file>res/instruments/instrsynthesizer.png</file> <file>res/instruments/synthesizer.png</file>
<file>res/instruments/instrvocal.png</file> <file>res/instruments/vocal.png</file>
<file>res/instruments/instrdjembe.png</file> <file>res/instruments/djembe.png</file>
<file>res/instruments/instrharmonica.png</file> <file>res/instruments/harmonica.png</file>
<file>res/instruments/instrrecorder.png</file> <file>res/instruments/recorder.png</file>
<file>res/instruments/instrlistener.png</file> <file>res/instruments/listener.png</file>
<file>res/instruments/instrstreamer.png</file> <file>res/instruments/streamer.png</file>
<file>res/instruments/instrguitarvocal.png</file> <file>res/instruments/guitarvocal.png</file>
<file>res/instruments/instrkeyboardvocal.png</file> <file>res/instruments/keyboardvocal.png</file>
<file>res/instruments/bodhran.png</file> <file>res/instruments/bodhran.png</file>
<file>res/instruments/bassoon.png</file> <file>res/instruments/bassoon.png</file>
<file>res/instruments/oboe.png</file> <file>res/instruments/oboe.png</file>
@ -71,6 +74,10 @@
<file>res/instruments/viola.png</file> <file>res/instruments/viola.png</file>
<file>res/instruments/congas.png</file> <file>res/instruments/congas.png</file>
<file>res/instruments/bongo.png</file> <file>res/instruments/bongo.png</file>
<file>res/instruments/vocalbass.png</file>
<file>res/instruments/vocaltenor.png</file>
<file>res/instruments/vocalalto.png</file>
<file>res/instruments/vocalsoprano.png</file>
</qresource> </qresource>
<qresource prefix="/png/main"> <qresource prefix="/png/main">
<file>res/fronticon.png</file> <file>res/fronticon.png</file>

View file

@ -340,6 +340,7 @@ CServer::CServer ( const int iNewMaxNumChan,
// allocate worst case memory for the temporary vectors // allocate worst case memory for the temporary vectors
vecChanIDsCurConChan.Init ( iMaxNumChannels ); vecChanIDsCurConChan.Init ( iMaxNumChannels );
vecvecdGains.Init ( iMaxNumChannels ); vecvecdGains.Init ( iMaxNumChannels );
vecvecdPannings.Init ( iMaxNumChannels );
vecvecsData.Init ( iMaxNumChannels ); vecvecsData.Init ( iMaxNumChannels );
vecNumAudioChannels.Init ( iMaxNumChannels ); vecNumAudioChannels.Init ( iMaxNumChannels );
vecNumFrameSizeConvBlocks.Init ( iMaxNumChannels ); vecNumFrameSizeConvBlocks.Init ( iMaxNumChannels );
@ -350,6 +351,7 @@ CServer::CServer ( const int iNewMaxNumChan,
{ {
// init vectors storing information of all channels // init vectors storing information of all channels
vecvecdGains[i].Init ( iMaxNumChannels ); vecvecdGains[i].Init ( iMaxNumChannels );
vecvecdPannings[i].Init ( iMaxNumChannels );
// we always use stereo audio buffers (see "vecsSendData") // we always use stereo audio buffers (see "vecsSendData")
vecvecsData[i].Init ( 2 /* stereo */ * DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES /* worst case buffer size */ ); vecvecsData[i].Init ( 2 /* stereo */ * DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES /* worst case buffer size */ );
@ -471,8 +473,8 @@ CServer::CServer ( const int iNewMaxNumChan,
this, SLOT ( OnAboutToQuit() ) ); this, SLOT ( OnAboutToQuit() ) );
QObject::connect ( pSignalHandler, QObject::connect ( pSignalHandler,
SIGNAL ( ShutdownSignal ( int ) ), SIGNAL ( HandledSignal ( int ) ),
this, SLOT ( OnShutdown ( int ) ) ); this, SLOT ( OnHandledSignal ( int ) ) );
connectChannelSignalsToServerSlots<MAX_NUM_CHANNELS>(); connectChannelSignalsToServerSlots<MAX_NUM_CHANNELS>();
@ -495,6 +497,9 @@ inline void CServer::connectChannelSignalsToServerSlots()
void ( CServer::* pOnChatTextReceivedCh )( QString ) = void ( CServer::* pOnChatTextReceivedCh )( QString ) =
&CServerSlots<slotId>::OnChatTextReceivedCh; &CServerSlots<slotId>::OnChatTextReceivedCh;
void ( CServer::* pOnMuteStateHasChangedCh )( int, bool ) =
&CServerSlots<slotId>::OnMuteStateHasChangedCh;
void ( CServer::* pOnServerAutoSockBufSizeChangeCh )( int ) = void ( CServer::* pOnServerAutoSockBufSizeChangeCh )( int ) =
&CServerSlots<slotId>::OnServerAutoSockBufSizeChangeCh; &CServerSlots<slotId>::OnServerAutoSockBufSizeChangeCh;
@ -514,6 +519,10 @@ inline void CServer::connectChannelSignalsToServerSlots()
QObject::connect ( &vecChannels[iCurChanID], &CChannel::ChatTextReceived, QObject::connect ( &vecChannels[iCurChanID], &CChannel::ChatTextReceived,
this, pOnChatTextReceivedCh ); this, pOnChatTextReceivedCh );
// other mute state has changed
QObject::connect ( &vecChannels[iCurChanID], &CChannel::MuteStateHasChanged,
this, pOnMuteStateHasChangedCh );
// auto socket buffer size change // auto socket buffer size change
QObject::connect ( &vecChannels[iCurChanID], &CChannel::ServerAutoSockBufSizeChange, QObject::connect ( &vecChannels[iCurChanID], &CChannel::ServerAutoSockBufSizeChange,
this, pOnServerAutoSockBufSizeChangeCh ); this, pOnServerAutoSockBufSizeChangeCh );
@ -597,6 +606,9 @@ CreateAndSendChanListForAllConChannels();
vecChannels[iChID].CreateLicReqMes ( eLicenceType ); vecChannels[iChID].CreateLicReqMes ( eLicenceType );
} }
// send version info (for, e.g., feature activation in the client)
vecChannels[iChID].CreateVersionAndOSMes();
// reset the conversion buffers // reset the conversion buffers
DoubleFrameSizeConvBufIn[iChID].Reset(); DoubleFrameSizeConvBufIn[iChID].Reset();
DoubleFrameSizeConvBufOut[iChID].Reset(); DoubleFrameSizeConvBufOut[iChID].Reset();
@ -665,10 +677,38 @@ void CServer::OnAboutToQuit()
} }
} }
void CServer::OnShutdown ( int ) void CServer::OnHandledSignal ( int sigNum )
{ {
#ifdef _WIN32
// Windows does not actually get OnHandledSignal triggered
QCoreApplication::instance()->exit();
Q_UNUSED ( sigNum )
#else
switch ( sigNum )
{
case SIGUSR1:
RequestNewRecording();
break;
case SIGINT:
case SIGTERM:
// This should trigger OnAboutToQuit // This should trigger OnAboutToQuit
QCoreApplication::instance()->exit(); QCoreApplication::instance()->exit();
break;
default:
break;
}
#endif
}
void CServer::RequestNewRecording()
{
if ( bEnableRecording )
{
emit RestartRecorder();
}
} }
void CServer::Start() void CServer::Start()
@ -706,7 +746,7 @@ void CServer::Stop()
void CServer::OnTimer() void CServer::OnTimer()
{ {
int i, j, iUnused; int i, j, iUnused;
int iClientFrameSizeSamples; int iClientFrameSizeSamples = 0; // initialize to avoid a compiler warning
OpusCustomDecoder* CurOpusDecoder; OpusCustomDecoder* CurOpusDecoder;
OpusCustomEncoder* CurOpusEncoder; OpusCustomEncoder* CurOpusEncoder;
unsigned char* pCurCodedData; unsigned char* pCurCodedData;
@ -813,6 +853,9 @@ JitterMeas.Measure();
// consider audio fade-in // consider audio fade-in
vecvecdGains[i][j] *= vecChannels[vecChanIDsCurConChan[j]].GetFadeInGain(); vecvecdGains[i][j] *= vecChannels[vecChanIDsCurConChan[j]].GetFadeInGain();
// panning
vecvecdPannings[i][j] = vecChannels[iCurChanID].GetPan ( vecChanIDsCurConChan[j] );
} }
// If the server frame size is smaller than the received OPUS frame size, we need a conversion // If the server frame size is smaller than the received OPUS frame size, we need a conversion
@ -940,6 +983,7 @@ JitterMeas.Measure();
// actual processing of audio data -> mix // actual processing of audio data -> mix
ProcessData ( vecvecsData, ProcessData ( vecvecsData,
vecvecdGains[i], vecvecdGains[i],
vecvecdPannings[i],
vecNumAudioChannels, vecNumAudioChannels,
vecsSendData, vecsSendData,
iCurNumAudChan, iCurNumAudChan,
@ -1042,6 +1086,7 @@ opus_custom_encoder_ctl ( CurOpusEncoder,
/// @brief Mix all audio data from all clients together. /// @brief Mix all audio data from all clients together.
void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData, void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
const CVector<double>& vecdGains, const CVector<double>& vecdGains,
const CVector<double>& vecdPannings,
const CVector<int>& vecNumAudioChannels, const CVector<int>& vecNumAudioChannels,
CVector<int16_t>& vecsOutData, CVector<int16_t>& vecsOutData,
const int iCurNumAudChan, const int iCurNumAudChan,
@ -1114,12 +1159,18 @@ void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
// Stereo target channel ----------------------------------------------- // Stereo target channel -----------------------------------------------
for ( j = 0; j < iNumClients; j++ ) for ( j = 0; j < iNumClients; j++ )
{ {
// get a reference to the audio data and gain of the current client // get a reference to the audio data and gain/pan of the current client
const CVector<int16_t>& vecsData = vecvecsData[j]; const CVector<int16_t>& vecsData = vecvecsData[j];
const double dGain = vecdGains[j]; const double dGain = vecdGains[j];
const double dPan = vecdPannings[j];
// calculate combined gain/pan for each stereo channel where we define
// the panning that center equals full gain for both channels
const double dGainL = std::min ( 0.5, 1 - dPan ) * 2 * dGain;
const double dGainR = std::min ( 0.5, dPan ) * 2 * dGain;
// if channel gain is 1, avoid multiplication for speed optimization // if channel gain is 1, avoid multiplication for speed optimization
if ( dGain == static_cast<double> ( 1.0 ) ) if ( ( dGainL == static_cast<double> ( 1.0 ) ) && ( dGainR == static_cast<double> ( 1.0 ) ) )
{ {
if ( vecNumAudioChannels[j] == 1 ) if ( vecNumAudioChannels[j] == 1 )
{ {
@ -1154,20 +1205,25 @@ void CServer::ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
{ {
// left channel // left channel
vecsOutData[k] = Double2Short ( vecsOutData[k] = Double2Short (
vecsOutData[k] + vecsData[i] * dGain ); vecsOutData[k] + vecsData[i] * dGain * dGainL );
// right channel // right channel
vecsOutData[k + 1] = Double2Short ( vecsOutData[k + 1] = Double2Short (
vecsOutData[k + 1] + vecsData[i] * dGain ); vecsOutData[k + 1] + vecsData[i] * dGain * dGainR );
} }
} }
else else
{ {
// stereo // stereo
for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i++ ) for ( i = 0; i < ( 2 * iServerFrameSizeSamples ); i += 2 )
{ {
// left channel
vecsOutData[i] = Double2Short ( vecsOutData[i] = Double2Short (
vecsOutData[i] + vecsData[i] * dGain ); vecsOutData[i] + vecsData[i] * dGain * dGainL );
// right channel
vecsOutData[i + 1] = Double2Short (
vecsOutData[i + 1] + vecsData[i + 1] * dGain * dGainR );
} }
} }
} }
@ -1261,6 +1317,17 @@ void CServer::CreateAndSendChatTextForAllConChannels ( const int iCurChanID
} }
} }
void CServer::CreateOtherMuteStateChanged ( const int iCurChanID,
const int iOtherChanID,
const bool bIsMuted )
{
if ( vecChannels[iOtherChanID].IsConnected() )
{
// send message
vecChannels[iOtherChanID].CreateMuteStateHasChangedMes ( iCurChanID, bIsMuted );
}
}
int CServer::GetFreeChan() int CServer::GetFreeChan()
{ {
// look for a free channel // look for a free channel

View file

@ -117,10 +117,10 @@ signals:
}; };
#endif #endif
template<unsigned int slotId> template<unsigned int slotId>
class CServerSlots : public CServerSlots<slotId - 1> class CServerSlots : public CServerSlots<slotId - 1>
{ {
public: public:
void OnSendProtMessCh ( CVector<uint8_t> mess ) { SendProtMessage ( slotId - 1, mess ); } void OnSendProtMessCh ( CVector<uint8_t> mess ) { SendProtMessage ( slotId - 1, mess ); }
void OnReqConnClientsListCh() { CreateAndSendChanListForThisChan ( slotId - 1 ); } void OnReqConnClientsListCh() { CreateAndSendChanListForThisChan ( slotId - 1 ); }
@ -130,6 +130,11 @@ public:
CreateAndSendChatTextForAllConChannels ( slotId - 1, strChatText ); CreateAndSendChatTextForAllConChannels ( slotId - 1, strChatText );
} }
void OnMuteStateHasChangedCh ( int iChanID, bool bIsMuted )
{
CreateOtherMuteStateChanged ( slotId - 1, iChanID, bIsMuted );
}
void OnServerAutoSockBufSizeChangeCh ( int iNNumFra ) void OnServerAutoSockBufSizeChangeCh ( int iNNumFra )
{ {
CreateAndSendJitBufMessage ( slotId - 1, iNNumFra ); CreateAndSendJitBufMessage ( slotId - 1, iNNumFra );
@ -144,6 +149,10 @@ protected:
virtual void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, virtual void CreateAndSendChatTextForAllConChannels ( const int iCurChanID,
const QString& strChatText ) = 0; const QString& strChatText ) = 0;
virtual void CreateOtherMuteStateChanged ( const int iCurChanID,
const int iOtherChanID,
const bool bIsMuted ) = 0;
virtual void CreateAndSendJitBufMessage ( const int iCurChanID, virtual void CreateAndSendJitBufMessage ( const int iCurChanID,
const int iNNumFra ) = 0; const int iNNumFra ) = 0;
}; };
@ -256,6 +265,10 @@ protected:
virtual void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, virtual void CreateAndSendChatTextForAllConChannels ( const int iCurChanID,
const QString& strChatText ); const QString& strChatText );
virtual void CreateOtherMuteStateChanged ( const int iCurChanID,
const int iOtherChanID,
const bool bIsMuted );
virtual void CreateAndSendJitBufMessage ( const int iCurChanID, virtual void CreateAndSendJitBufMessage ( const int iCurChanID,
const int iNNumFra ); const int iNNumFra );
@ -269,6 +282,7 @@ protected:
void ProcessData ( const CVector<CVector<int16_t> >& vecvecsData, void ProcessData ( const CVector<CVector<int16_t> >& vecvecsData,
const CVector<double>& vecdGains, const CVector<double>& vecdGains,
const CVector<double>& vecdPannings,
const CVector<int>& vecNumAudioChannels, const CVector<int>& vecNumAudioChannels,
CVector<int16_t>& vecsOutData, CVector<int16_t>& vecsOutData,
const int iCurNumAudChan, const int iCurNumAudChan,
@ -285,6 +299,8 @@ protected:
const CVector<CVector<int16_t> > vecvecsData, const CVector<CVector<int16_t> > vecvecsData,
CVector<uint16_t>& vecLevelsOut ); CVector<uint16_t>& vecLevelsOut );
void RequestNewRecording();
// do not use the vector class since CChannel does not have appropriate // do not use the vector class since CChannel does not have appropriate
// copy constructor/operator // copy constructor/operator
CChannel vecChannels[MAX_NUM_CHANNELS]; CChannel vecChannels[MAX_NUM_CHANNELS];
@ -310,6 +326,7 @@ protected:
CVector<int> vecChanIDsCurConChan; CVector<int> vecChanIDsCurConChan;
CVector<CVector<double> > vecvecdGains; CVector<CVector<double> > vecvecdGains;
CVector<CVector<double> > vecvecdPannings;
CVector<CVector<int16_t> > vecvecsData; CVector<CVector<int16_t> > vecvecsData;
CVector<int> vecNumAudioChannels; CVector<int> vecNumAudioChannels;
CVector<int> vecNumFrameSizeConvBlocks; CVector<int> vecNumFrameSizeConvBlocks;
@ -364,6 +381,7 @@ signals:
const CHostAddress RecHostAddr, const CHostAddress RecHostAddr,
const int iNumAudChan, const int iNumAudChan,
const CVector<int16_t> vecsData ); const CVector<int16_t> vecsData );
void RestartRecorder();
public slots: public slots:
void OnTimer(); void OnTimer();
@ -441,5 +459,5 @@ public slots:
void OnAboutToQuit(); void OnAboutToQuit();
void OnShutdown ( int ); void OnHandledSignal ( int sigNum );
}; };

View file

@ -66,14 +66,14 @@ CServerDlg::CServerDlg ( CServer* pNServP,
tr ( "If the Make My Server Public check box is checked, this server registers " tr ( "If the Make My Server Public check box is checked, this server registers "
"itself at the central server so that all " ) + APP_NAME + "itself at the central server so that all " ) + APP_NAME +
tr ( " users can see the server in the connect dialog server list and " tr ( " users can see the server in the connect dialog server list and "
"connect to it. The registering of the server is renewed periodically " "connect to it. The registration of the server is renewed periodically "
"to make sure that all servers in the connect dialog server list are " "to make sure that all servers in the connect dialog server list are "
"actually available." ) ); "actually available." ) );
// register server status label // register server status label
lblRegSvrStatus->setWhatsThis ( "<b>" + tr ( "Register Server Status" ) + ":</b> " + lblRegSvrStatus->setWhatsThis ( "<b>" + tr ( "Register Server Status" ) + ":</b> " +
tr ( "If the Make My Server Public check box is checked, this will show " tr ( "If the Make My Server Public check box is checked, this will show "
"the success of registration with the central server." ) ); "whether registration with the central server is successful." ) );
// central server address // central server address
QString strCentrServAddr = "<b>" + tr ( "Central Server Address" ) + ":</b> " + QString strCentrServAddr = "<b>" + tr ( "Central Server Address" ) + ":</b> " +
@ -188,9 +188,11 @@ lvwClients->setMinimumHeight ( 140 );
// central server address type combo box // central server address type combo box
cbxCentServAddrType->clear(); cbxCentServAddrType->clear();
cbxCentServAddrType->addItem ( tr ( "Manual" ) ); // AT_MANUAL cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_CUSTOM ) );
cbxCentServAddrType->addItem ( tr ( "Default" ) ); // AT_DEFAULT cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_DEFAULT ) );
cbxCentServAddrType->addItem ( tr ( "Default (North America)" ) ); // AT_NORTH_AMERICA cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENERAL_NORTHAMERICA ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENRE_ROCK ) );
cbxCentServAddrType->addItem ( csCentServAddrTypeToString ( AT_GENRE_JAZZ ) );
cbxCentServAddrType->setCurrentIndex ( static_cast<int> ( pServer->GetCentralServerAddressType() ) ); cbxCentServAddrType->setCurrentIndex ( static_cast<int> ( pServer->GetCentralServerAddressType() ) );
// update server name line edit // update server name line edit
@ -506,7 +508,7 @@ void CServerDlg::UpdateGUIDependencies()
// get the states which define the GUI dependencies from the server // get the states which define the GUI dependencies from the server
const bool bCurSerListEnabled = pServer->GetServerListEnabled(); const bool bCurSerListEnabled = pServer->GetServerListEnabled();
const bool bCurUseDefCentServAddr = ( pServer->GetCentralServerAddressType() != AT_MANUAL ); const bool bCurUseDefCentServAddr = ( pServer->GetCentralServerAddressType() != AT_CUSTOM );
const ESvrRegStatus eSvrRegStatus = pServer->GetSvrRegStatus(); const ESvrRegStatus eSvrRegStatus = pServer->GetSvrRegStatus();
@ -522,7 +524,7 @@ void CServerDlg::UpdateGUIDependencies()
{ {
// if the default central server is used, just show a text of the // if the default central server is used, just show a text of the
// server name // server name
edtCentralServerAddress->setText ( DEFAULT_SERVER_NAME ); edtCentralServerAddress->setText ( tr ( "Predefined Address" ) );
} }
else else
{ {

View file

@ -33,7 +33,7 @@ CServerListManager::CServerListManager ( const quint16 iNPortNum,
CProtocol* pNConLProt ) CProtocol* pNConLProt )
: tsConsoleStream ( *( ( new ConsoleWriterFactory() )->get() ) ), : tsConsoleStream ( *( ( new ConsoleWriterFactory() )->get() ) ),
iNumPredefinedServers ( 0 ), iNumPredefinedServers ( 0 ),
eCentralServerAddressType ( AT_MANUAL ), // must be AT_MANUAL for the "no GUI" case eCentralServerAddressType ( AT_CUSTOM ), // must be AT_CUSTOM for the "no GUI" case
bCentServPingServerInList ( bNCentServPingServerInList ), bCentServPingServerInList ( bNCentServPingServerInList ),
pConnLessProtocol ( pNConLProt ), pConnLessProtocol ( pNConLProt ),
eSvrRegStatus ( SRS_UNREGISTERED ), eSvrRegStatus ( SRS_UNREGISTERED ),
@ -206,7 +206,7 @@ void CServerListManager::SetCentralServerAddress ( const QString sNCentServAddr
( (
( !strCentralServerAddress.toLower().compare ( "localhost" ) || ( !strCentralServerAddress.toLower().compare ( "localhost" ) ||
!strCentralServerAddress.compare ( "127.0.0.1" ) ) && !strCentralServerAddress.compare ( "127.0.0.1" ) ) &&
( eCentralServerAddressType == AT_MANUAL ) ( eCentralServerAddressType == AT_CUSTOM )
); );
bEnabled = true; bEnabled = true;

View file

@ -77,6 +77,17 @@ void CSettings::Load()
} }
} }
// stored pan values
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{
if ( GetNumericIniSet ( IniXMLDocument, "client",
QString ( "storedpanvalue%1" ).arg ( iIdx ),
0, AUD_MIX_PAN_MAX/2, iValue ) )
{
pClient->vecStoredPanValues[iIdx] = iValue;
}
}
// stored fader solo state // stored fader solo state
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ ) for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{ {
@ -288,7 +299,7 @@ void CSettings::Load()
// central server address type // central server address type
if ( GetNumericIniSet ( IniXMLDocument, "client", "centservaddrtype", if ( GetNumericIniSet ( IniXMLDocument, "client", "centservaddrtype",
0, 2 /* AT_NORTH_AMERICA */, iValue ) ) 0, 4 /* AT_GENRE_JAZZ */, iValue ) )
{ {
pClient->SetCentralServerAddressType ( static_cast<ECSAddType> ( iValue ) ); pClient->SetCentralServerAddressType ( static_cast<ECSAddType> ( iValue ) );
} }
@ -304,7 +315,7 @@ if ( GetFlagIniSet ( IniXMLDocument, "client", "defcentservaddr", bValue ) )
// only the case that manual was set in old ini must be considered // only the case that manual was set in old ini must be considered
if ( !bValue ) if ( !bValue )
{ {
pClient->SetCentralServerAddressType ( AT_MANUAL ); pClient->SetCentralServerAddressType ( AT_CUSTOM );
} }
} }
@ -359,7 +370,7 @@ if ( GetFlagIniSet ( IniXMLDocument, "client", "defcentservaddr", bValue ) )
// central server address type (note that it is important // central server address type (note that it is important
// to set this setting prior to the "central server address") // to set this setting prior to the "central server address")
if ( GetNumericIniSet ( IniXMLDocument, "server", "centservaddrtype", if ( GetNumericIniSet ( IniXMLDocument, "server", "centservaddrtype",
0, 2 /* AT_NORTH_AMERICA */, iValue ) ) 0, 4 /* AT_GENRE_JAZZ */, iValue ) )
{ {
pServer->SetCentralServerAddressType ( static_cast<ECSAddType> ( iValue ) ); pServer->SetCentralServerAddressType ( static_cast<ECSAddType> ( iValue ) );
} }
@ -375,7 +386,7 @@ if ( GetFlagIniSet ( IniXMLDocument, "server", "defcentservaddr", bValue ) )
// only the case that manual was set in old ini must be considered // only the case that manual was set in old ini must be considered
if ( !bValue ) if ( !bValue )
{ {
pServer->SetCentralServerAddressType ( AT_MANUAL ); pServer->SetCentralServerAddressType ( AT_CUSTOM );
} }
} }
@ -455,6 +466,14 @@ void CSettings::Save()
pClient->vecStoredFaderLevels[iIdx] ); pClient->vecStoredFaderLevels[iIdx] );
} }
// stored pan values
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{
SetNumericIniSet ( IniXMLDocument, "client",
QString ( "storedpanvalue%1" ).arg ( iIdx ),
pClient->vecStoredPanValues[iIdx] );
}
// stored fader solo states // stored fader solo states
for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ ) for ( iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
{ {

View file

@ -75,7 +75,7 @@ CSignalHandler* CSignalHandler::getSingletonP() { return singleton; }
bool CSignalHandler::emitSignal ( int sigNum ) bool CSignalHandler::emitSignal ( int sigNum )
{ {
return QMetaObject::invokeMethod( singleton, "ShutdownSignal", Qt::QueuedConnection, Q_ARG( int, sigNum ) ); return QMetaObject::invokeMethod( singleton, "HandledSignal", Qt::QueuedConnection, Q_ARG( int, sigNum ) );
} }
#ifndef _WIN32 #ifndef _WIN32
@ -124,11 +124,11 @@ QReadWriteLock* CSignalWin::getLock() const
return &lock; return &lock;
} }
BOOL WINAPI CSignalWin::signalHandler ( _In_ DWORD sigNum ) BOOL WINAPI CSignalWin::signalHandler ( _In_ DWORD )
{ {
auto self = getSelf<CSignalWin>(); auto self = getSelf<CSignalWin>();
QReadLocker lock ( self->getLock() ); QReadLocker lock ( self->getLock() );
return self->pSignalHandler->emitSignal ( static_cast<int>( sigNum ) ); return self->pSignalHandler->emitSignal ( -1 );
} }
#else #else
@ -145,12 +145,14 @@ CSignalUnix::CSignalUnix ( CSignalHandler* nPSignalHandler ) :
socketNotifier->setEnabled ( true ); socketNotifier->setEnabled ( true );
setSignalHandled ( SIGUSR1, true );
setSignalHandled ( SIGINT, true ); setSignalHandled ( SIGINT, true );
setSignalHandled ( SIGTERM, true ); setSignalHandled ( SIGTERM, true );
} }
} }
CSignalUnix::~CSignalUnix() { CSignalUnix::~CSignalUnix() {
setSignalHandled ( SIGUSR1, false );
setSignalHandled ( SIGINT, false ); setSignalHandled ( SIGINT, false );
setSignalHandled ( SIGTERM, false ); setSignalHandled ( SIGTERM, false );
} }

View file

@ -104,7 +104,7 @@ public slots:
#endif #endif
signals: signals:
void ShutdownSignal ( int sigNum ); void HandledSignal ( int sigNum );
private: private:
QScopedPointer<CSignalBase> pSignalBase; QScopedPointer<CSignalBase> pSignalBase;
@ -153,7 +153,7 @@ public:
private: private:
mutable QReadWriteLock lock; mutable QReadWriteLock lock;
static BOOL WINAPI signalHandler ( _In_ DWORD sigNum ); static BOOL WINAPI signalHandler ( _In_ DWORD );
}; };
#else #else

View file

@ -139,7 +139,7 @@ QString CSoundBase::SetDev ( const int iNewDev )
// software anymore // software anymore
QMessageBox::critical ( QMessageBox::critical (
nullptr, APP_NAME, QString ( tr ( "The audio driver properties " nullptr, APP_NAME, QString ( tr ( "The audio driver properties "
"have changed to a state which is incompatible to this " "have changed to a state which is incompatible with this "
"software. The selected audio device could not be used " "software. The selected audio device could not be used "
"because of the following error:" ) + " <b>" ) + "because of the following error:" ) + " <b>" ) +
strErrorMessage + strErrorMessage +

View file

@ -393,6 +393,7 @@ CAboutDlg::CAboutDlg ( QWidget* parent ) : QDialog ( parent )
"<p>Simon Tomlinson (<a href=""https://github.com/sthenos"">sthenos</a>)</p>" "<p>Simon Tomlinson (<a href=""https://github.com/sthenos"">sthenos</a>)</p>"
"<p>Marc jr. Landolt (<a href=""https://github.com/braindef"">braindef</a>)</p>" "<p>Marc jr. Landolt (<a href=""https://github.com/braindef"">braindef</a>)</p>"
"<p>Olivier Humbert (<a href=""https://github.com/trebmuh"">trebmuh</a>)</p>" "<p>Olivier Humbert (<a href=""https://github.com/trebmuh"">trebmuh</a>)</p>"
"<p>Tarmo Johannes (<a href=""https://github.com/tarmoj"">tarmoj</a>)</p>"
"<p>mirabilos (<a href=""https://github.com/mirabilos"">mirabilos</a>)</p>" "<p>mirabilos (<a href=""https://github.com/mirabilos"">mirabilos</a>)</p>"
"<p>newlaurent62 (<a href=""https://github.com/newlaurent62"">newlaurent62</a>)</p>" "<p>newlaurent62 (<a href=""https://github.com/newlaurent62"">newlaurent62</a>)</p>"
"<p>Emlyn Bolton (<a href=""https://github.com/emlynmac"">emlynmac</a>)</p>" "<p>Emlyn Bolton (<a href=""https://github.com/emlynmac"">emlynmac</a>)</p>"
@ -704,8 +705,8 @@ CMusProfDlg::CMusProfDlg ( CClient* pNCliP,
QString strFaderTag = "<b>" + tr ( "Musician Profile" ) + ":</b> " + tr ( QString strFaderTag = "<b>" + tr ( "Musician Profile" ) + ":</b> " + tr (
"Set your name or an alias here so that the other musicians you want to play with " "Set your name or an alias here so that the other musicians you want to play with "
"know who you are. Additionally you may set an instrument picture of " "know who you are. Additionally you may set an instrument picture of "
"the instrument you play and a flag of the country you are living. " "the instrument you play and a flag of the country you are living in. "
"The city you live in and the skill level of playing your instrument " "The city you live in and the skill level playing your instrument "
"may also be added." ) + "<br>" + tr ( "may also be added." ) + "<br>" + tr (
"What you set here will appear at your fader on the mixer board when " "What you set here will appear at your fader on the mixer board when "
"you are connected to a " ) + APP_NAME + tr ( " server. This tag will " "you are connected to a " ) + APP_NAME + tr ( " server. This tag will "
@ -950,8 +951,10 @@ QString NetworkUtil::GetCentralServerAddress ( const ECSAddType eCentralServerAd
{ {
switch ( eCentralServerAddressType ) switch ( eCentralServerAddressType )
{ {
case AT_MANUAL: return strCentralServerAddress; case AT_CUSTOM: return strCentralServerAddress;
case AT_NORTH_AMERICA: return QString ( "%1:%2" ).arg ( DEFAULT_SERVER_ADDRESS ).arg ( DEFAULT_PORT_NUMBER_NORTHAMERICA ); case AT_GENERAL_NORTHAMERICA: return CENTSERV_GENERAL_NORTHAMERICA;
case AT_GENRE_ROCK: return CENTSERV_GENRE_ROCK;
case AT_GENRE_JAZZ: return CENTSERV_GENRE_JAZZ;
default: return DEFAULT_SERVER_ADDRESS; // AT_DEFAULT default: return DEFAULT_SERVER_ADDRESS; // AT_DEFAULT
} }
} }
@ -970,34 +973,34 @@ CVector<CInstPictures::CInstPictProps>& CInstPictures::GetTable()
// instrument picture data base initialization // instrument picture data base initialization
// NOTE: Do not change the order of any instrument in the future! // NOTE: Do not change the order of any instrument in the future!
// NOTE: The very first entry is the "not used" element per definition. // NOTE: The very first entry is the "not used" element per definition.
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "None" ), ":/png/instr/res/instruments/instrnone.png", IC_OTHER_INSTRUMENT ) ); // special first element vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "None" ), ":/png/instr/res/instruments/none.png", IC_OTHER_INSTRUMENT ) ); // special first element
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Drum Set" ), ":/png/instr/res/instruments/instrdrumset.png", IC_PERCUSSION_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Drum Set" ), ":/png/instr/res/instruments/drumset.png", IC_PERCUSSION_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Djembe" ), ":/png/instr/res/instruments/instrdjembe.png", IC_PERCUSSION_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Djembe" ), ":/png/instr/res/instruments/djembe.png", IC_PERCUSSION_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Electric Guitar" ), ":/png/instr/res/instruments/instreguitar.png", IC_PLUCKING_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Electric Guitar" ), ":/png/instr/res/instruments/eguitar.png", IC_PLUCKING_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Acoustic Guitar" ), ":/png/instr/res/instruments/instraguitar.png", IC_PLUCKING_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Acoustic Guitar" ), ":/png/instr/res/instruments/aguitar.png", IC_PLUCKING_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bass Guitar" ), ":/png/instr/res/instruments/instrbassguitar.png", IC_PLUCKING_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bass Guitar" ), ":/png/instr/res/instruments/bassguitar.png", IC_PLUCKING_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Keyboard" ), ":/png/instr/res/instruments/instrkeyboard.png", IC_KEYBOARD_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Keyboard" ), ":/png/instr/res/instruments/keyboard.png", IC_KEYBOARD_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Synthesizer" ), ":/png/instr/res/instruments/instrsynthesizer.png", IC_KEYBOARD_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Synthesizer" ), ":/png/instr/res/instruments/synthesizer.png", IC_KEYBOARD_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Grand Piano" ), ":/png/instr/res/instruments/instrgrandpiano.png", IC_KEYBOARD_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Grand Piano" ), ":/png/instr/res/instruments/grandpiano.png", IC_KEYBOARD_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Accordion" ), ":/png/instr/res/instruments/instraccordeon.png", IC_KEYBOARD_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Accordion" ), ":/png/instr/res/instruments/accordeon.png", IC_KEYBOARD_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Vocal" ), ":/png/instr/res/instruments/instrvocal.png", IC_OTHER_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Vocal" ), ":/png/instr/res/instruments/vocal.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Microphone" ), ":/png/instr/res/instruments/instrmicrophone.png", IC_OTHER_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Microphone" ), ":/png/instr/res/instruments/microphone.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Harmonica" ), ":/png/instr/res/instruments/instrharmonica.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Harmonica" ), ":/png/instr/res/instruments/harmonica.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Trumpet" ), ":/png/instr/res/instruments/instrtrumpet.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Trumpet" ), ":/png/instr/res/instruments/trumpet.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Trombone" ), ":/png/instr/res/instruments/instrtrombone.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Trombone" ), ":/png/instr/res/instruments/trombone.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "French Horn" ), ":/png/instr/res/instruments/instrfrenchhorn.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "French Horn" ), ":/png/instr/res/instruments/frenchhorn.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Tuba" ), ":/png/instr/res/instruments/instrtuba.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Tuba" ), ":/png/instr/res/instruments/tuba.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Saxophone" ), ":/png/instr/res/instruments/instrsaxophone.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Saxophone" ), ":/png/instr/res/instruments/saxophone.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Clarinet" ), ":/png/instr/res/instruments/instrclarinet.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Clarinet" ), ":/png/instr/res/instruments/clarinet.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Flute" ), ":/png/instr/res/instruments/instrflute.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Flute" ), ":/png/instr/res/instruments/flute.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Violin" ), ":/png/instr/res/instruments/instrviolin.png", IC_STRING_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Violin" ), ":/png/instr/res/instruments/violin.png", IC_STRING_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Cello" ), ":/png/instr/res/instruments/instrcello.png", IC_STRING_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Cello" ), ":/png/instr/res/instruments/cello.png", IC_STRING_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Double Bass" ), ":/png/instr/res/instruments/instrdoublebass.png", IC_STRING_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Double Bass" ), ":/png/instr/res/instruments/doublebass.png", IC_STRING_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Recorder" ), ":/png/instr/res/instruments/instrrecorder.png", IC_OTHER_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Recorder" ), ":/png/instr/res/instruments/recorder.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Streamer" ), ":/png/instr/res/instruments/instrstreamer.png", IC_OTHER_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Streamer" ), ":/png/instr/res/instruments/streamer.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Listener" ), ":/png/instr/res/instruments/instrlistener.png", IC_OTHER_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Listener" ), ":/png/instr/res/instruments/listener.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Guitar+Vocal" ), ":/png/instr/res/instruments/instrguitarvocal.png", IC_MULTIPLE_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Guitar+Vocal" ), ":/png/instr/res/instruments/guitarvocal.png", IC_MULTIPLE_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Keyboard+Vocal" ), ":/png/instr/res/instruments/instrkeyboardvocal.png", IC_MULTIPLE_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Keyboard+Vocal" ), ":/png/instr/res/instruments/keyboardvocal.png", IC_MULTIPLE_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bodhran" ), ":/png/instr/res/instruments/bodhran.png", IC_PERCUSSION_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bodhran" ), ":/png/instr/res/instruments/bodhran.png", IC_PERCUSSION_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bassoon" ), ":/png/instr/res/instruments/bassoon.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bassoon" ), ":/png/instr/res/instruments/bassoon.png", IC_WIND_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Oboe" ), ":/png/instr/res/instruments/oboe.png", IC_WIND_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Oboe" ), ":/png/instr/res/instruments/oboe.png", IC_WIND_INSTRUMENT ) );
@ -1005,6 +1008,10 @@ CVector<CInstPictures::CInstPictProps>& CInstPictures::GetTable()
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Viola" ), ":/png/instr/res/instruments/viola.png", IC_STRING_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Viola" ), ":/png/instr/res/instruments/viola.png", IC_STRING_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Congas" ), ":/png/instr/res/instruments/congas.png", IC_PERCUSSION_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Congas" ), ":/png/instr/res/instruments/congas.png", IC_PERCUSSION_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bongo" ), ":/png/instr/res/instruments/bongo.png", IC_PERCUSSION_INSTRUMENT ) ); vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Bongo" ), ":/png/instr/res/instruments/bongo.png", IC_PERCUSSION_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Vocal Bass" ), ":/png/instr/res/instruments/vocalbass.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Vocal Tenor" ), ":/png/instr/res/instruments/vocaltenor.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Vocal Alto" ), ":/png/instr/res/instruments/vocalalto.png", IC_OTHER_INSTRUMENT ) );
vecDataBase.Add ( CInstPictProps ( QCoreApplication::translate ( "CMusProfDlg", "Vocal Soprano" ), ":/png/instr/res/instruments/vocalsoprano.png", IC_OTHER_INSTRUMENT ) );
// now the table is initialized // now the table is initialized
TableIsInitialized = true; TableIsInitialized = true;
@ -1328,7 +1335,7 @@ ECSAddType CLocale::GetCentralServerAddressType ( const QLocale::Country eCountr
case QLocale::Canada: case QLocale::Canada:
case QLocale::Mexico: case QLocale::Mexico:
case QLocale::Greenland: case QLocale::Greenland:
return AT_NORTH_AMERICA; return AT_GENERAL_NORTHAMERICA;
default: default:
return AT_DEFAULT; return AT_DEFAULT;

View file

@ -565,11 +565,35 @@ enum ELicenceType
// Central server address type ------------------------------------------------- // Central server address type -------------------------------------------------
enum ECSAddType enum ECSAddType
{ {
AT_MANUAL = 0, // used for settings -> enum values must be fixed!
AT_DEFAULT = 1, // Europe and others AT_CUSTOM = 0,
AT_NORTH_AMERICA = 2 AT_DEFAULT = 1,
AT_GENERAL_NORTHAMERICA = 2,
AT_GENRE_ROCK = 3,
AT_GENRE_JAZZ = 4
}; };
inline QString csCentServAddrTypeToString ( ECSAddType eAddrType )
{
switch ( eAddrType )
{
case AT_CUSTOM:
return QCoreApplication::translate ( "CClientSettingsDlg", "Custom" );
case AT_GENERAL_NORTHAMERICA:
return QCoreApplication::translate ( "CClientSettingsDlg", "All Genres" );
case AT_GENRE_ROCK:
return QCoreApplication::translate ( "CClientSettingsDlg", "Genre Rock" );
case AT_GENRE_JAZZ:
return QCoreApplication::translate ( "CClientSettingsDlg", "Genre Jazz" );
default: // AT_DEFAULT
return QCoreApplication::translate ( "CClientSettingsDlg", "Default" );
}
}
// Slave server registration state --------------------------------------------- // Slave server registration state ---------------------------------------------
enum ESvrRegStatus enum ESvrRegStatus

View file

@ -118,7 +118,7 @@ QString CSound::CheckDeviceCapabilities()
( SetSaRateReturn == ASE_NotPresent ) ) ( SetSaRateReturn == ASE_NotPresent ) )
{ {
// return error string // return error string
return tr ( "The audio device does not support to set the required sampling " return tr ( "The audio device does not support setting the required sampling "
"rate. This error can happen if you have an audio interface like the " "rate. This error can happen if you have an audio interface like the "
"Roland UA-25EX where you set the sample rate with a hardware switch " "Roland UA-25EX where you set the sample rate with a hardware switch "
"on the audio device. If this is the case, please change the sample rate " "on the audio device. If this is the case, please change the sample rate "
@ -517,7 +517,7 @@ CSound::CSound ( void (*fpNewCallback) ( CVector<int16_t>& psData, voi
{ {
throw CGenErr ( "<b>" + tr ( "No ASIO audio device (driver) found." ) + "</b><br><br>" + throw CGenErr ( "<b>" + tr ( "No ASIO audio device (driver) found." ) + "</b><br><br>" +
tr ( "The " ) + APP_NAME + tr ( " software requires the low latency audio " tr ( "The " ) + APP_NAME + tr ( " software requires the low latency audio "
"interface ASIO to work properly. This is no standard " "interface ASIO to work properly. This is not a standard "
"Windows audio interface and therefore a special audio driver is " "Windows audio interface and therefore a special audio driver is "
"required. Either your sound card has a native ASIO driver (which " "required. Either your sound card has a native ASIO driver (which "
"is recommended) or you might want to use alternative drivers like " "is recommended) or you might want to use alternative drivers like "