mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-03-02 05:25:41 +00:00
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 commitb1936e76ab. * Revert "default fullscreen for built-in settings." This reverts commitea89584174. * Revert "9a9151b9" *9a9151b9* fake_audio to fakeAudio
This commit is contained in:
@ -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
BIN
msvc/projectM.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 98 KiB |
@ -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
|
||||
|
||||
@ -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 "$(MSBuildThisFileDirectory)..\LICENSE.txt" "$(OutDir)LICENSE.txt"" />
|
||||
<Exec Command="copy /Y "$(MSBuildThisFileDirectory)..\AUTHORS.txt" "$(OutDir)AUTHORS.txt"" />
|
||||
<Exec Command="copy /Y "$(MSBuildThisFileDirectory)..\README.md" "$(OutDir)README.md"" />
|
||||
<Exec Command="copy /Y "$(MSBuildThisFileDirectory)projectM.ico" "$(OutDir)projectM.ico"" />
|
||||
<Exec Command="copy /Y "$(MSBuildThisFileDirectory)projectm_qDj_icon.ico" "$(OutDir)projectm_qDj_icon.ico"" />
|
||||
<Exec Command="copy /Y "$(MSBuildThisFileDirectory)Setup.iss" "$(OutDir)Setup.iss"" />
|
||||
<Exec Command="copy /Y "$(MSBuildThisFileDirectory)setup_inno.bmp" "$(OutDir)setup_inno.bmp"" />
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user