a mega cool windows xp app

Compare changes

Choose any two refs to compare.

.github/images/ss.png

This is a binary file and will not be displayed.

.github/images/ss.webp

This is a binary file and will not be displayed.

+1
.gitignore
···
.clangd
compile_commands.json
build/
+
ShortwaveRadioInstaller.exe
+8 -4
CMakeLists.txt
···
add_compile_options(-fno-threadsafe-statics)
add_compile_options(-D_GLIBCXX_HAS_GTHREADS=0)
-
add_executable(ShortwaveApp WIN32 main.cpp)
+
if(MINGW)
+
set(WIN32_ICON shortwave.rc)
+
endif()
+
+
add_executable(ShortwaveApp WIN32 main.cpp ${WIN32_ICON})
# Add BASS library from libs directory
target_include_directories(ShortwaveApp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
···
target_include_directories(ShortwaveApp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
# Minimal static linking and avoid threading dependencies
-
target_link_options(ShortwaveApp PRIVATE
-
-static-libgcc
+
target_link_options(ShortwaveApp PRIVATE
+
-static-libgcc
-static-libstdc++
-static
-Wl,--subsystem,windows:5.01
···
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${OUTPUT_DIR}"
)
-
endif()
+
endif()
+2
CRUSH.md
···
## Build & Development Commands
- **Build**: `nix build`
- Compiles Shortwave Radio application
+
- **Build Installer**: `nix build .#installer` or `build-installer`
+
- Creates Windows installer (ShortwaveRadioInstaller.exe)
- **Dev Setup**: `setup-dev`
- Generates `compile_commands.json`
- **Deploy**: `deploy-to-xp`
+18 -44
README.md
···
# Shortwave
-
an app for [rewind](https://rewind.hackclub.com/#)
-
-
![a screenshot of windows xp with a text editor open saying "this will be a very cool app soon; just you wait"](https://raw.githubusercontent.com/taciturnaxolotl/shortwave/main/.github/images/ss.webp)
-
-
## Install
-
-
You can download a pre-built binary from the releases or build it yourself using the nix flake.
-
-
## Development
-
-
this project uses nix for cross-compilation to windows xp. the key was using an older nixpkgs (22.05) since newer mingw toolchains use windows apis that don't exist in xp.
-
-
### Quick Start
-
-
```bash
-
# enter the dev environment (or use direnv)
-
nix develop
-
-
# build the app
-
nix build
-
-
# deploy to my xp vm folder
-
deploy-to-xp
-
```
-
-
### Editor Setup (Zed)
-
-
to get proper intellisense for win32 apis in zed:
-
-
```bash
-
# generate .clangd config with proper mingw headers
-
setup-dev
+
a vintage shortwave radio tuner with internet streaming for [rewind](https://rewind.hackclub.com/#)
-
# restart zed
-
```
+
![a screenshot of windows xp with the app open to Jazz Radio: Smooth Jazz](https://raw.githubusercontent.com/taciturnaxolotl/shortwave/main/.github/images/ss.webp)
-
this creates a `.clangd` file that points to the actual mingw-w64 headers and avoids gcc intrinsics that cause clang issues.
+
### Radio Stations
-
### Build Details
+
| Frequency (MHz) | Station Name | Description |
+
|-----------------|---------------------|--------------------------------|
+
| 10.230 | SomaFM Groove | Downtempo and chillout |
+
| 11.470 | WBGO Jazz88 | Jazz from Newark |
+
| 12.650 | Radio Paradise | Eclectic music mix |
+
| 13.890 | Classical Music | Classical radio |
+
| 15.120 | Jazz Radio | Smooth jazz |
+
| 16.350 | FIP | Eclectic French radio |
+
| 18.810 | TSF Jazz | French jazz radio |
+
| 20.040 | Dublab | Electronic and experimental |
+
| 21.270 | BBC World Service | Global news and culture |
+
| 23.730 | WFMU | Freeform experimental radio |
+
| 24.960 | ChillHop Music | Lo-fi hip hop |
+
| 27.420 | Worldwide FM | Global music discovery |
-
- uses mingw-w64 cross-compiler targeting i686-w64-mingw32
-
- statically links runtime to avoid dll dependencies
-
- targets windows xp (winver=0x0501) for maximum compatibility
-
- older nixpkgs (22.05) prevents "procedure entry point" errors on xp
-
-
~
-
-
written in cpp. If you have any suggestions or issues feel free to open an issue on my [tangled](https://tangled.sh/@dunkirk.sh/shortwave) knot
+
written in cpp; this project uses nix for cross-compilation to windows xp. the key was using an older nixpkgs (22.05) since newer mingw toolchains use windows apis that don't exist in xp. if you have any suggestions or need to open a ticket please do so on my [tangled](https://tangled.sh/@dunkirk.sh/shortwave) knot
<p align="center">
<img src="https://raw.githubusercontent.com/taciturnaxolotl/carriage/master/.github/images/line-break.svg" />
+55 -53
flake.nix
···
deploy-to-xp = pkgs.writeShellScriptBin "deploy-to-xp" ''
echo "rebuilding program"
-
if ! nix build --rebuild; then
-
echo "Rebuild failed, attempting normal build..."
-
nix build
-
fi
+
nix build
XP_DIR="$HOME/Documents/xp-drive"
mkdir -p "$XP_DIR"
···
ls -la "$XP_DIR"/*.{exe,dll} 2>/dev/null || echo "No files found"
'';
+
build-installer = pkgs.writeShellScriptBin "build-installer" ''
+
echo "Building Shortwave Radio installer..."
+
nix build .#installer
+
+
if [ -f result/bin/ShortwaveRadioInstaller.exe ]; then
+
echo "โœ“ Installer built successfully: result/bin/ShortwaveRadioInstaller.exe"
+
ls -la result/bin/ShortwaveRadioInstaller.exe
+
else
+
echo "โœ— Installer build failed"
+
exit 1
+
fi
+
'';
+
default = self'.packages.shortwave;
};
···
cmake
pkgsCross.mingw32.buildPackages.gcc
self'.packages.deploy-to-xp
+
self'.packages.build-installer
+
nsis
];
shellHook = ''
-
echo "Shortwave Radio development environment loaded"
-
echo "Available commands:"
-
echo " nix build - Build the Shortwave Radio application"
-
echo " deploy-to-xp - Deploy to XP VM folder"
-
echo ""
-
echo "Setting up development environment..."
-
-
# Get dynamic paths from nix packages
-
GCC_BASE="${pkgs.pkgsCross.mingw32.buildPackages.gcc}/i686-w64-mingw32"
-
SYS_INCLUDE="$GCC_BASE/sys-include"
-
MINGW_MAIN_INCLUDE="${pkgs.pkgsCross.mingw32.windows.mingw_w64.dev}/include"
-
CPP_INCLUDE="${pkgs.lib.getDev pkgs.pkgsCross.mingw32.buildPackages.gcc}/include/c++/10.3.0"
-
CPP_TARGET_INCLUDE="$CPP_INCLUDE/i686-w64-mingw32"
-
-
# Auto-generate .clangd config with correct paths
-
cat > .clangd << EOF
-
CompileFlags:
-
Add:
-
- -target
-
- i686-w64-mingw32
-
- -DWINVER=0x0501
-
- -D_WIN32_WINNT=0x0501
-
- -DWIN32_LEAN_AND_MEAN
-
- -D_WIN32
-
- -DWIN32
-
- -std=c++17
-
- -fno-builtin
-
- -isystem
-
- $SYS_INCLUDE
-
- -isystem
-
- $MINGW_MAIN_INCLUDE
-
- -isystem
-
- $CPP_INCLUDE
-
- -isystem
-
- $CPP_TARGET_INCLUDE
-
Remove:
-
- -I*/gcc/*/include
-
EOF
+
# Get dynamic paths from nix packages
+
GCC_BASE="${pkgs.pkgsCross.mingw32.buildPackages.gcc}/i686-w64-mingw32"
+
SYS_INCLUDE="$GCC_BASE/sys-include"
+
MINGW_MAIN_INCLUDE="${pkgs.pkgsCross.mingw32.windows.mingw_w64.dev}/include"
+
CPP_INCLUDE="${pkgs.lib.getDev pkgs.pkgsCross.mingw32.buildPackages.gcc}/include/c++/10.3.0"
+
CPP_TARGET_INCLUDE="$CPP_INCLUDE/i686-w64-mingw32"
-
cat > compile_commands.json << EOF
-
[
-
{
-
"directory": "$(pwd)",
-
"command": "i686-w64-mingw32-g++ -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 -DWIN32_LEAN_AND_MEAN -D_WIN32 -DWIN32 -std=c++17 -isystem \"$SYS_INCLUDE\" -isystem \"$MINGW_MAIN_INCLUDE\" -isystem \"$CPP_INCLUDE\" -isystem \"$CPP_TARGET_INCLUDE\" -c main.cpp",
-
"file": "main.cpp"
-
}
-
]
-
EOF
+
# Auto-generate .clangd config with correct paths
+
cat > .clangd <<EOF
+
CompileFlags:
+
Add:
+
- -target
+
- i686-w64-mingw32
+
- -DWINVER=0x0501
+
- -D_WIN32_WINNT=0x0501
+
- -DWIN32_LEAN_AND_MEAN
+
- -D_WIN32
+
- -DWIN32
+
- -std=c++17
+
- -fno-builtin
+
- -isystem
+
- $SYS_INCLUDE
+
- -isystem
+
- $MINGW_MAIN_INCLUDE
+
- -isystem
+
- $CPP_INCLUDE
+
- -isystem
+
- $CPP_TARGET_INCLUDE
+
Remove:
+
- -I*/gcc/*/include
+
EOF
-
echo "โœ“ Generated .clangd config and compile_commands.json with include paths"
-
echo "โœ“ Development environment ready for Shortwave Radio development"
+
cat > compile_commands.json <<EOF
+
[
+
{
+
"directory": "$(pwd)",
+
"command": "i686-w64-mingw32-g++ -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 -DWIN32_LEAN_AND_MEAN -D_WIN32 -DWIN32 -std=c++17 -isystem \"$SYS_INCLUDE\" -isystem \"$MINGW_MAIN_INCLUDE\" -isystem \"$CPP_INCLUDE\" -isystem \"$CPP_TARGET_INCLUDE\" -c main.cpp",
+
"file": "main.cpp"
+
}
+
]
+
EOF
'';
};
};
icon.aseprite

This is a binary file and will not be displayed.

+114
installer.nsi
···
+
; Shortwave Radio Installer
+
; Compatible with Windows XP and later
+
+
!define APPNAME "Shortwave Radio"
+
!define COMPANYNAME "Kieran Klukas"
+
!define DESCRIPTION "Vintage Shortwave Radio Tuner with Internet Streaming"
+
!define VERSIONMAJOR 1
+
!define VERSIONMINOR 0
+
!define VERSIONBUILD 0
+
!define HELPURL "https://github.com/taciturnaxolotl/shortwave"
+
!define UPDATEURL "https://github.com/taciturnaxolotl/shortwave/releases"
+
!define ABOUTURL "https://github.com/taciturnaxolotl/shortwave"
+
!define INSTALLSIZE 2048
+
+
; Disable CRC check to avoid cross-platform issues
+
CRCCheck off
+
; Use solid compression
+
SetCompressor /SOLID lzma
+
+
RequestExecutionLevel admin
+
InstallDir "$PROGRAMFILES\${APPNAME}"
+
Name "${APPNAME}"
+
outFile "ShortwaveRadioInstaller.exe"
+
+
!include LogicLib.nsh
+
+
page directory
+
page instfiles
+
+
!macro VerifyUserIsAdmin
+
UserInfo::GetAccountType
+
pop $0
+
${If} $0 != "admin"
+
messageBox mb_iconstop "Administrator rights required!"
+
setErrorLevel 740
+
quit
+
${EndIf}
+
!macroend
+
+
function .onInit
+
setShellVarContext all
+
!insertmacro VerifyUserIsAdmin
+
functionEnd
+
+
section "install"
+
setOutPath $INSTDIR
+
+
; Main executable
+
file "result/bin/Shortwave.exe"
+
+
; BASS audio library
+
file "libs/bass.dll"
+
+
; License and documentation
+
file "LICENSE.md"
+
file "README.md"
+
+
; Create uninstaller
+
writeUninstaller "$INSTDIR\uninstall.exe"
+
+
; Start menu shortcuts
+
createDirectory "$SMPROGRAMS\${APPNAME}"
+
createShortCut "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" "$INSTDIR\Shortwave.exe"
+
createShortCut "$SMPROGRAMS\${APPNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe"
+
+
; Desktop shortcut
+
createShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\Shortwave.exe"
+
+
; Registry entries for Add/Remove Programs
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME} - ${DESCRIPTION}"
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "InstallLocation" "$\"$INSTDIR$\""
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$\"$INSTDIR\Shortwave.exe$\""
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "Publisher" "${COMPANYNAME}"
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "HelpLink" "${HELPURL}"
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLUpdateInfo" "${UPDATEURL}"
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLInfoAbout" "${ABOUTURL}"
+
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayVersion" "${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}"
+
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMajor" ${VERSIONMAJOR}
+
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMinor" ${VERSIONMINOR}
+
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoModify" 1
+
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoRepair" 1
+
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "EstimatedSize" ${INSTALLSIZE}
+
sectionEnd
+
+
function un.onInit
+
SetShellVarContext all
+
MessageBox MB_OKCANCEL "Remove ${APPNAME}?" IDOK next
+
Abort
+
next:
+
!insertmacro VerifyUserIsAdmin
+
functionEnd
+
+
section "uninstall"
+
; Remove files
+
delete "$INSTDIR\Shortwave.exe"
+
delete "$INSTDIR\bass.dll"
+
delete "$INSTDIR\LICENSE.md"
+
delete "$INSTDIR\README.md"
+
delete "$INSTDIR\uninstall.exe"
+
+
; Remove shortcuts
+
delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk"
+
delete "$SMPROGRAMS\${APPNAME}\Uninstall.lnk"
+
rmDir "$SMPROGRAMS\${APPNAME}"
+
delete "$DESKTOP\${APPNAME}.lnk"
+
+
; Remove registry entries
+
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
+
+
; Remove installation directory
+
rmDir "$INSTDIR"
+
sectionEnd
+62 -22
main.cpp
···
} RadioStation;
RadioStation g_stations[] = {
-
{14.230f, "SomaFM Groove", "Downtempo and chillout", "http://ice1.somafm.com/groovesalad-128-mp3"},
-
{15.770f, "Radio Paradise", "Eclectic music mix", "http://stream.radioparadise.com/mp3-128"},
-
{17.895f, "Jazz Radio", "Smooth jazz", "http://jazz-wr04.ice.infomaniak.ch/jazz-wr04-128.mp3"},
-
{21.500f, "Classical Music", "Classical radio", "http://stream.wqxr.org/wqxr"},
+
{10.230f, "SomaFM Groove", "Downtempo and chillout", "http://ice1.somafm.com/groovesalad-128-mp3"},
+
{11.470f, "WBGO Jazz88", "Jazz from Newark", "http://wbgo.streamguys.net/wbgo128"},
+
{12.650f, "Radio Paradise", "Eclectic music mix", "http://stream.radioparadise.com/mp3-128"},
+
{13.890f, "Classical Music", "Classical radio", "http://stream.wqxr.org/wqxr"},
+
{15.120f, "Jazz Radio", "Smooth jazz", "http://jazz-wr04.ice.infomaniak.ch/jazz-wr04-128.mp3"},
+
{16.350f, "FIP", "Eclectic French radio", "http://direct.fipradio.fr/live/fip-midfi.mp3"},
+
{18.810f, "TSF Jazz", "French jazz radio", "http://tsfjazz.ice.infomaniak.ch/tsfjazz-high.mp3"},
+
{20.040f, "Dublab", "Electronic and experimental", "http://dublab.out.airtime.pro:8000/dublab_a"},
+
{21.270f, "BBC World Service", "Global news and culture", "http://stream.live.vc.bbcmedia.co.uk/bbc_world_service"},
+
{23.730f, "WFMU", "Freeform experimental radio", "http://stream0.wfmu.org/freeform-128k"},
+
{24.960f, "ChillHop Music", "Lo-fi hip hop", "http://ice1.somafm.com/fluid"},
+
{27.420f, "Worldwide FM", "Global music discovery", "http://worldwidefm.out.airtime.pro:8000/worldwidefm_a"},
};
#define NUM_STATIONS (sizeof(g_stations) / sizeof(RadioStation))
···
void StartStaticNoise();
void StopStaticNoise();
void UpdateStaticVolume(float signalStrength);
+
void UpdateStreamVolume();
// VU meter functions
void UpdateVULevels();
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
// Don't allocate console by default - will be toggled via menu
-
+
const char* CLASS_NAME = "ShortwaveRadio";
WNDCLASS wc = {};
···
if (g_radio.signalStrength > 100) g_radio.signalStrength = 100;
UpdateStaticVolume(g_radio.signalStrength);
+
UpdateStreamVolume();
InvalidateRect(hwnd, NULL, TRUE);
break;
}
···
if (g_radio.signalStrength > 100) g_radio.signalStrength = 100;
UpdateStaticVolume(g_radio.signalStrength);
+
UpdateStreamVolume();
InvalidateRect(hwnd, NULL, TRUE);
break;
}
···
if (g_radio.signalStrength > 100) g_radio.signalStrength = 100;
UpdateStaticVolume(g_radio.signalStrength);
+
UpdateStreamVolume();
InvalidateRect(hwnd, NULL, TRUE);
break;
}
···
if (g_radio.signalStrength > 100) g_radio.signalStrength = 100;
UpdateStaticVolume(g_radio.signalStrength);
+
UpdateStreamVolume();
InvalidateRect(hwnd, NULL, TRUE);
break;
}
···
// Main panel with simplified metallic gradient effect
RECT panel = {10, 10, rect->right - 10, rect->bottom - 10};
-
+
// Simplified gradient effect with fewer steps
for (int i = 0; i < 8; i++) {
int gray = 45 + i * 3;
···
RadioStation* currentStation = FindNearestStation(g_radio.frequency);
if (currentStation && g_radio.signalStrength > 30) {
RECT stationRect = {50, 320, 550, 360};
-
+
// Winamp-style display background
HBRUSH displayBrush = CreateSolidBrush(RGB(0, 0, 0));
FillRect(hdc, &stationRect, displayBrush);
···
// Beveled border
HPEN lightBorderPen = CreatePen(PS_SOLID, 1, RGB(64, 64, 64));
HPEN darkBorderPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
-
+
SelectObject(hdc, darkBorderPen);
MoveToEx(hdc, stationRect.left, stationRect.bottom, NULL);
LineTo(hdc, stationRect.left, stationRect.top);
LineTo(hdc, stationRect.right, stationRect.top);
-
+
SelectObject(hdc, lightBorderPen);
LineTo(hdc, stationRect.right, stationRect.bottom);
LineTo(hdc, stationRect.left, stationRect.bottom);
-
+
DeleteObject(lightBorderPen);
DeleteObject(darkBorderPen);
···
void DrawFrequencyDisplay(HDC hdc, int x, int y, float frequency) {
// Winamp-style LCD display with beveled edges
RECT display = {x - 100, y - 25, x + 100, y + 25};
-
+
// Dark background
HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
FillRect(hdc, &display, blackBrush);
···
sprintf(freqText, "%.3f MHz", frequency);
SetBkMode(hdc, TRANSPARENT);
-
+
// Create glow effect by drawing text multiple times with slight offsets
HFONT lcdFont = CreateFont(20, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
···
void DrawSignalMeter(HDC hdc, int x, int y, int strength) {
// Winamp-style meter background with bevel
RECT meter = {x, y, x + 80, y + 20};
-
+
// Dark background
HBRUSH meterBrush = CreateSolidBrush(RGB(16, 16, 16));
FillRect(hdc, &meter, meterBrush);
···
void DrawVUMeter(HDC hdc, int x, int y, float leftLevel, float rightLevel) {
// Winamp-style VU meter with classic look
RECT meterBg = {x, y, x + 80, y + 40};
-
+
// Dark background
HBRUSH bgBrush = CreateSolidBrush(RGB(16, 16, 16));
FillRect(hdc, &meterBg, bgBrush);
···
int leftWidth = (int)(leftLevel * 65);
if (leftWidth > 0) {
RECT leftBar = {x + 8, y + 12, x + 8 + leftWidth, y + 17};
-
+
// Determine color based on level
COLORREF leftColor;
if (leftLevel > 0.8f) leftColor = RGB(255, 64, 64); // Red
···
int rightWidth = (int)(rightLevel * 65);
if (rightWidth > 0) {
RECT rightBar = {x + 8, y + 22, x + 8 + rightWidth, y + 27};
-
+
// Determine color based on level
COLORREF rightColor;
if (rightLevel > 0.8f) rightColor = RGB(255, 64, 64); // Red
···
if (g_radio.signalStrength > 100) g_radio.signalStrength = 100;
UpdateStaticVolume(g_radio.signalStrength);
+
UpdateStreamVolume();
void UpdateVolumeFromMouse(int mouseX, int mouseY) {
···
if (g_radio.volume < 0.0f) g_radio.volume = 0.0f;
if (g_radio.volume > 1.0f) g_radio.volume = 1.0f;
-
// Update static volume when main volume changes
+
// Update volumes when main volume changes
UpdateStaticVolume(g_radio.signalStrength);
+
UpdateStreamVolume();
int InitializeAudio() {
···
+
void UpdateStreamVolume() {
+
if (g_audio.currentStream) {
+
// Stream volume based on signal strength and radio volume
+
float volume = g_radio.volume * (g_radio.signalStrength / 100.0f);
+
BASS_ChannelSetAttribute(g_audio.currentStream, BASS_ATTRIB_VOL, volume);
+
if (g_consoleVisible) {
+
printf("Updated stream volume to: %.2f\n", volume);
+
}
+
}
+
}
+
void UpdateVULevels() {
// Initialize levels to zero
g_audio.vuLevelLeft = 0.0f;
···
if (g_audio.currentStream && BASS_ChannelIsActive(g_audio.currentStream) == BASS_ACTIVE_PLAYING) {
DWORD level = BASS_ChannelGetLevel(g_audio.currentStream);
if (level != -1) {
-
// Extract left and right channel levels
-
g_audio.vuLevelLeft = (float)LOWORD(level) / 32768.0f;
-
g_audio.vuLevelRight = (float)HIWORD(level) / 32768.0f;
+
// Extract left and right channel levels and apply volume scaling
+
float rawLeft = (float)LOWORD(level) / 32768.0f;
+
float rawRight = (float)HIWORD(level) / 32768.0f;
+
+
// Apply the same volume scaling as the actual audio output
+
float streamVolume = g_radio.volume * (g_radio.signalStrength / 100.0f);
+
g_audio.vuLevelLeft = rawLeft * streamVolume;
+
g_audio.vuLevelRight = rawRight * streamVolume;
···
float staticLeft = (float)LOWORD(staticLevel) / 32768.0f;
float staticRight = (float)HIWORD(staticLevel) / 32768.0f;
+
// Apply static volume scaling
+
float staticVolume = (100.0f - g_radio.signalStrength) / 100.0f;
+
float scaledStaticVolume = g_radio.volume * staticVolume * g_audio.staticVolume;
+
+
// Ensure minimum static when radio is on but no strong signal
+
if (g_radio.power && g_radio.signalStrength < 50.0f) {
+
scaledStaticVolume = fmax(scaledStaticVolume, g_radio.volume * 0.1f);
+
}
+
// Combine with existing levels (simulate mixing)
-
g_audio.vuLevelLeft = fmin(1.0f, g_audio.vuLevelLeft + staticLeft * 0.3f);
-
g_audio.vuLevelRight = fmin(1.0f, g_audio.vuLevelRight + staticRight * 0.3f);
+
g_audio.vuLevelLeft = fmin(1.0f, g_audio.vuLevelLeft + staticLeft * scaledStaticVolume * 0.3f);
+
g_audio.vuLevelRight = fmin(1.0f, g_audio.vuLevelRight + staticRight * scaledStaticVolume * 0.3f);
shortwave.ico

This is a binary file and will not be displayed.

+1
shortwave.rc
···
+
IDI_ICON1 ICON DISCARDABLE "shortwave.ico"