Little things (#368)

* Noise not needed - F4 shows if shaders are compiled.

* Don't compile native presets by default in Visual Studio

* Debug / duplicate info

* Missed a debug native preset.

* Make texture errors more clear - we failed looking for multiple extensions.

* Move images from presets folder to textures folder

* Documented missing textures.

* Undo Visual Studio version bump.

* Renable NativePresetFactory (but the example native presets remain disabled)

* Comment

* Fixes / updates to audio device toggling.

* Stop crashing if there is no input microphone. Make fake audio dynamic so it can be enabled if there is no mic.

* Remove debug output.

* Document VC++ redist requirement.

* F4 missing from SDL help menu.

* Windows app instead of Console (no more cmd.exe pop-up when launching).

* Fullscreen for built-in settings.

* New icon (based on github and idle preset and consistent with Steam)

* Change language for loopback / audio changing.

* default fullscreen for built-in settings.

* Revert "Fullscreen for built-in settings."

This reverts commit b1936e76ab.

* Revert "default fullscreen for built-in settings."

This reverts commit ea89584174.

* Revert "9a9151b9"

* 9a9151b9

* fake_audio to fakeAudio
This commit is contained in:
milkdropper
2020-07-28 23:05:35 +04:00
committed by GitHub
parent f2ca861b08
commit c5533e3efe
9 changed files with 127 additions and 92 deletions

View File

@ -11,6 +11,7 @@ Its purpose in life is to read an audio input and to produce mesmerizing visuals
### Available For
* [macOS, Linux (binary)](https://github.com/projectM-visualizer/projectm/releases)
* [Windows Store (PC, XBOX, Phone)](https://www.microsoft.com/store/apps/9NDCVH0VCWJN)
* [Windows (standalone binary)](https://github.com/projectM-visualizer/projectm/releases) (Requires the latest [Visual C++ redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads))
* [Android](https://play.google.com/store/apps/details?id=com.psperl.projectM)
* [iOS](https://itunes.apple.com/us/app/projectm-music-visualizer/id530922227?mt=8&ign-mpt=uo%3D4)
* [iTunes plugin (macOS)](https://github.com/projectM-visualizer/projectm/releases/)

BIN
msvc/projectM.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -62,27 +62,17 @@ Global
{013DE011-EC24-3643-A8EE-F2609E7E4741}.Release|x64.ActiveCfg = Release|x64
{013DE011-EC24-3643-A8EE-F2609E7E4741}.Release|x64.Build.0 = Release|x64
{55A71B6A-5C7E-30D5-8210-302A8D2080DB}.Debug|x64.ActiveCfg = Debug|x64
{55A71B6A-5C7E-30D5-8210-302A8D2080DB}.Debug|x64.Build.0 = Debug|x64
{55A71B6A-5C7E-30D5-8210-302A8D2080DB}.Release|x64.ActiveCfg = Release|x64
{55A71B6A-5C7E-30D5-8210-302A8D2080DB}.Release|x64.Build.0 = Release|x64
{9260C46C-6BC9-396F-9310-6BAAD56A7801}.Debug|x64.ActiveCfg = Debug|x64
{9260C46C-6BC9-396F-9310-6BAAD56A7801}.Release|x64.ActiveCfg = Release|x64
{7A203034-A4D7-3A2B-9138-CB125F9B35E6}.Debug|x64.ActiveCfg = Debug|x64
{7A203034-A4D7-3A2B-9138-CB125F9B35E6}.Debug|x64.Build.0 = Debug|x64
{7A203034-A4D7-3A2B-9138-CB125F9B35E6}.Release|x64.ActiveCfg = Release|x64
{7A203034-A4D7-3A2B-9138-CB125F9B35E6}.Release|x64.Build.0 = Release|x64
{6E418BC8-5407-3A37-96BD-5201D47DE753}.Debug|x64.ActiveCfg = Debug|x64
{6E418BC8-5407-3A37-96BD-5201D47DE753}.Debug|x64.Build.0 = Debug|x64
{6E418BC8-5407-3A37-96BD-5201D47DE753}.Release|x64.ActiveCfg = Release|x64
{6E418BC8-5407-3A37-96BD-5201D47DE753}.Release|x64.Build.0 = Release|x64
{B7C4937F-A36D-3B6C-A8AC-CA99772AE5EC}.Debug|x64.ActiveCfg = Debug|x64
{B7C4937F-A36D-3B6C-A8AC-CA99772AE5EC}.Debug|x64.Build.0 = Debug|x64
{B7C4937F-A36D-3B6C-A8AC-CA99772AE5EC}.Release|x64.ActiveCfg = Release|x64
{B7C4937F-A36D-3B6C-A8AC-CA99772AE5EC}.Release|x64.Build.0 = Release|x64
{27DDCE71-E33B-3521-92B5-9918356D78A1}.Debug|x64.ActiveCfg = Debug|x64
{27DDCE71-E33B-3521-92B5-9918356D78A1}.Debug|x64.Build.0 = Debug|x64
{27DDCE71-E33B-3521-92B5-9918356D78A1}.Release|x64.ActiveCfg = Release|x64
{27DDCE71-E33B-3521-92B5-9918356D78A1}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -89,7 +89,7 @@
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<ImportLibrary>projectM-sdl/Debug/projectMSDL.lib</ImportLibrary>
<ProgramDataBaseFile>projectM-sdl/Debug/projectMSDL.pdb</ProgramDataBaseFile>
<SubSystem>Console</SubSystem>
<SubSystem>Windows</SubSystem>
</Link>
<ProjectReference>
<LinkLibraryDependencies>false</LinkLibraryDependencies>
@ -133,7 +133,7 @@
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<ImportLibrary>projectM-sdl/Release/projectMSDL.lib</ImportLibrary>
<ProgramDataBaseFile>projectM-sdl/Release/projectMSDL.pdb</ProgramDataBaseFile>
<SubSystem>Console</SubSystem>
<SubSystem>Windows</SubSystem>
</Link>
<ProjectReference>
<LinkLibraryDependencies>false</LinkLibraryDependencies>
@ -176,7 +176,7 @@
<ResourceCompile Include="projectM.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="projectm_qDj_icon.ico">
<Image Include="projectM.ico">
<DeploymentContent>true</DeploymentContent>
</Image>
</ItemGroup>
@ -208,6 +208,7 @@
<Exec Command="copy /Y &quot;$(MSBuildThisFileDirectory)..\LICENSE.txt&quot; &quot;$(OutDir)LICENSE.txt&quot;" />
<Exec Command="copy /Y &quot;$(MSBuildThisFileDirectory)..\AUTHORS.txt&quot; &quot;$(OutDir)AUTHORS.txt&quot;" />
<Exec Command="copy /Y &quot;$(MSBuildThisFileDirectory)..\README.md&quot; &quot;$(OutDir)README.md&quot;" />
<Exec Command="copy /Y &quot;$(MSBuildThisFileDirectory)projectM.ico&quot; &quot;$(OutDir)projectM.ico&quot;" />
<Exec Command="copy /Y &quot;$(MSBuildThisFileDirectory)projectm_qDj_icon.ico&quot; &quot;$(OutDir)projectm_qDj_icon.ico&quot;" />
<Exec Command="copy /Y &quot;$(MSBuildThisFileDirectory)Setup.iss&quot; &quot;$(OutDir)Setup.iss&quot;" />
<Exec Command="copy /Y &quot;$(MSBuildThisFileDirectory)setup_inno.bmp&quot; &quot;$(OutDir)setup_inno.bmp&quot;" />

View File

@ -16,7 +16,9 @@ std::string PresetFactory::protocol(const std::string & url, std::string & path)
else {
path = url.substr(pos + 3, url.length());
// std::cout << "[PresetFactory] path is " << path << std::endl;
#ifdef DEBUG
std::cout << "[PresetFactory] url is " << url << std::endl;
#endif
return url.substr(0, pos);
}

View File

@ -765,7 +765,9 @@ GLuint ShaderEngine::compilePresetShader(const PresentShaderType shaderType, Sha
}
if (ret != GL_FALSE) {
#ifdef DEBUG
std::cerr << "Successful compilation of " << shaderTypeString << std::endl;
#endif
} else {
std::cerr << "Compilation error (step3) of " << shaderTypeString << std::endl;

View File

@ -61,27 +61,45 @@ void projectMSDL::audioInputCallbackS16(void *userdata, unsigned char *stream, i
app->pcm()->addPCM16(pcm16);
}
SDL_AudioDeviceID projectMSDL::selectAudioInput(int _count) {
// TODO: implement some sort of UI allowing the user to select which audio input device they would like to use
// ask the user which capture device to use
// printf("Please select which audio input to use:\n");
printf("Detected devices:\n");
for (int i = 0; i < _count; i++) {
printf(" %i: 🎤%s\n", i, SDL_GetAudioDeviceName(i, true));
}
return 0;
}
int projectMSDL::toggleAudioInput() {
CurAudioDevice++;
if (CurAudioDevice >= NumAudioDevices)
// trigger a toggle with CMD-I or CTRL-I
if (wasapi) { // we are currently on WASAPI, so we are going to revert to a microphone/line-in input.
if (this->openAudioInput())
this->beginAudioCapture();
CurAudioDevice = 0;
selectedAudioDevice = CurAudioDevice;
initAudioInput();
selectedAudioDevice = CurAudioDevice;
this->wasapi = false; // Track wasapi as off so projectMSDL will stop listening to WASAPI loopback in pmSDL_main.
}
else {
this->endAudioCapture(); // end current audio capture.
CurAudioDevice++; // iterate device index
if (CurAudioDevice >= NumAudioDevices) { // We reached outside the boundaries of available audio devices.
CurAudioDevice = 0; // Return to first audio device in the index.
#ifdef WASAPI_LOOPBACK
// If we are at the boundary and WASAPI is enabled then let's load WASAPI instead.
projectM::setToastMessage("Loopback audio selected");
SDL_Log("Loopback audio selected");
this->fakeAudio = false; // disable fakeAudio in case it was enabled.
this->wasapi = true; // Track wasapi as on so projectMSDL will listen to it.
#else
if (NumAudioDevices == 1) // If WASAPI_LOOPBACK was not enabled and there is only one audio device, it's pointless to toggle anything.
{
SDL_Log("There is only one audio capture device. There is nothing to toggle at this time.");
return 1;
}
// If WASAPI_LOOPBACK is not enabled and we have multiple input devices, return to device index 0 and let's listen to that device.
selectedAudioDevice = CurAudioDevice;
initAudioInput();
this->beginAudioCapture();
#endif
}
else {
// This is a normal scenario where we move forward in the audio device index.
selectedAudioDevice = CurAudioDevice;
initAudioInput();
this->beginAudioCapture();
}
}
return 1;
}
@ -105,15 +123,17 @@ int projectMSDL::initAudioInput() {
if (audioDeviceID == 0) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to open audio capture device: %s", SDL_GetError());
SDL_Quit();
return 0;
}
// read characteristics of opened capture device
SDL_Log("Opened audio capture device index=%i devId=%i: %s", selectedAudioDevice, audioDeviceID, SDL_GetAudioDeviceName(selectedAudioDevice, true));
std::string deviceToast = "Listening to ";
deviceToast += SDL_GetAudioDeviceName(selectedAudioDevice, true);
std::string deviceToast = SDL_GetAudioDeviceName(selectedAudioDevice, true); // Example: Microphone rear
deviceToast += " selected";
projectM::setToastMessage(deviceToast);
#ifdef DEBUG
SDL_Log("Samples: %i, frequency: %i, channels: %i, format: %i", have.samples, have.freq, have.channels, have.format);
#endif
audioChannelsCount = have.channels;
audioSampleRate = have.freq;
audioSampleCount = have.samples;
@ -124,9 +144,12 @@ int projectMSDL::initAudioInput() {
}
int projectMSDL::openAudioInput() {
fakeAudio = false; // if we are opening an audio input then there is no need for fake audio.
// get audio driver name (static)
#ifdef DEBUG
const char* driver_name = SDL_GetCurrentAudioDriver();
SDL_Log("Using audio driver: %s\n", driver_name);
#endif
// get audio input device
unsigned int i;
@ -135,23 +158,18 @@ int projectMSDL::openAudioInput() {
CurAudioDevice = 0;
if (NumAudioDevices == 0) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "No audio capture devices found");
SDL_Quit();
projectM::setToastMessage("No audio capture devices found: using simulated audio");
fakeAudio = true;
return 0;
}
#ifdef DEBUG
for (i = 0; i < NumAudioDevices; i++) {
SDL_Log("Found audio capture device %d: %s", i, SDL_GetAudioDeviceName(i, true));
}
#endif
// device to open
// default selected Audio Device to 0.
selectedAudioDevice = 0;
if (NumAudioDevices > 1) {
// need to choose which input device to use
selectedAudioDevice = selectAudioInput(CurAudioDevice);
if (selectedAudioDevice > NumAudioDevices) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "No audio input device specified.");
SDL_Quit();
}
}
initAudioInput();
return 1;
@ -164,6 +182,7 @@ void projectMSDL::beginAudioCapture() {
void projectMSDL::endAudioCapture() {
SDL_PauseAudioDevice(audioDeviceID, true);
SDL_CloseAudioDevice(audioDeviceID);
}
void projectMSDL::setHelpText(const std::string & helpText) {
@ -465,6 +484,10 @@ void projectMSDL::init(SDL_Window *window, SDL_GLContext *_glCtx, const bool _re
glCtx = _glCtx;
projectM_resetGL(width, height);
#ifdef WASAPI_LOOPBACK
wasapi = true;
#endif
// are we rendering to a texture?
renderToTexture = _renderToTexture;
if (renderToTexture) {

View File

@ -88,6 +88,8 @@ public:
bool done;
bool wasapi = false; // Used to track if wasapi is currently active. This bool will allow us to run a WASAPI app and still toggle to microphone inputs.
bool fakeAudio = false; // Used to track fake audio, so we can turn it off and on.
projectMSDL(Settings settings, int flags);
projectMSDL(std::string config_file, int flags);
void init(SDL_Window *window, SDL_GLContext *glCtx, const bool renderToTexture = false);
@ -135,7 +137,6 @@ private:
static void audioInputCallbackS16(void *userdata, unsigned char *stream, int len);
void keyHandler(SDL_Event *);
SDL_AudioDeviceID selectAudioInput(int _count);
void renderTexture();
};

View File

@ -268,7 +268,7 @@ srand((int)(time(NULL)));
ERR(L"pAudioClient->Start error");
return hr;
}
bool bDone = false;
bool bFirstPacket = true;
UINT32 nPasses = 0;
@ -420,6 +420,7 @@ modKey = "CMD";
std::string sdlHelpMenu = "\n"
"F1: This help menu""\n"
"F3: Show preset name""\n"
"F4: Show details and statistics""\n"
"F5: Show FPS""\n"
"L or SPACE: Lock/Unlock Preset""\n"
"R: Random preset""\n"
@ -447,9 +448,16 @@ modKey = "CMD";
#endif
#if !FAKE_AUDIO && !WASAPI_LOOPBACK
// get an audio input device
if (app->openAudioInput())
app->beginAudioCapture();
// get an audio input device
if (app->openAudioInput())
app->beginAudioCapture();
#endif
#ifdef WASAPI_LOOPBACK
// Default to WASAPI loopback if it was enabled at compilation.
app->wasapi = true;
// Notify that loopback capture was started.
SDL_Log("Opened audio capture loopback.");
#endif
#if TEST_ALL_PRESETS
@ -488,52 +496,58 @@ modKey = "CMD";
while (! app->done) {
app->renderFrame();
#if FAKE_AUDIO
app->addFakePCM();
app->fakeAudio = true;
#endif
// fakeAudio can also be enabled dynamically.
if (app->fakeAudio )
{
app->addFakePCM();
}
#ifdef WASAPI_LOOPBACK
// drain data while it is available
nPasses++;
UINT32 nNextPacketSize;
for (
hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize);
SUCCEEDED(hr) && nNextPacketSize > 0;
hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize)
) {
// get the captured data
BYTE *pData;
UINT32 nNumFramesToRead;
DWORD dwFlags;
if (app->wasapi) {
// drain data while it is available
nPasses++;
UINT32 nNextPacketSize;
for (
hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize);
SUCCEEDED(hr) && nNextPacketSize > 0;
hr = pAudioCaptureClient->GetNextPacketSize(&nNextPacketSize)
) {
// get the captured data
BYTE *pData;
UINT32 nNumFramesToRead;
DWORD dwFlags;
hr = pAudioCaptureClient->GetBuffer(
&pData,
&nNumFramesToRead,
&dwFlags,
NULL,
NULL
);
if (FAILED(hr)) {
return hr;
}
LONG lBytesToWrite = nNumFramesToRead * nBlockAlign;
/** Add the waveform data */
app->pcm()->addPCMfloat((float *)pData, nNumFramesToRead);
*pnFrames += nNumFramesToRead;
hr = pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
if (FAILED(hr)) {
return hr;
}
bFirstPacket = false;
}
hr = pAudioCaptureClient->GetBuffer(
&pData,
&nNumFramesToRead,
&dwFlags,
NULL,
NULL
);
if (FAILED(hr)) {
return hr;
}
LONG lBytesToWrite = nNumFramesToRead * nBlockAlign;
/** Add the waveform data */
app->pcm()->addPCMfloat((float *)pData, nNumFramesToRead);
*pnFrames += nNumFramesToRead;
hr = pAudioCaptureClient->ReleaseBuffer(nNumFramesToRead);
if (FAILED(hr)) {
return hr;
}
bFirstPacket = false;
}
if (FAILED(hr)) {
return hr;
}
#endif /** WASAPI_LOOPBACK */
#if UNLOCK_FPS
@ -555,8 +569,9 @@ modKey = "CMD";
}
SDL_GL_DeleteContext(glCtx);
#if !FAKE_AUDIO && !WASAPI_LOOPBACK
app->endAudioCapture();
#if !FAKE_AUDIO
if (!app->wasapi) // not currently using WASAPI, so we need to endAudioCapture.
app->endAudioCapture();
#endif
// Write back config with current app settings (if we loaded from a config file to begin with)