Skip to content

Commit 8179c47

Browse files
committed
Created new, rewritten projectM SDL app.
0 parents  commit 8179c47

21 files changed

+2202
-0
lines changed

.gitignore

+1,040
Large diffs are not rendered by default.

CMakeLists.txt

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
2+
3+
if(CMAKE_VERSION VERSION_LESS 3.19 AND CMAKE_GENERATOR STREQUAL "Xcode")
4+
message(AUTHOR_WARNING "Using a CMake version before 3.19 with a recent Xcode SDK and the Xcode generator "
5+
"will likely result in CMake failing to find the AppleClang compiler. Either upgrade CMake to at least "
6+
"version 3.19 or use a different generator, e.g. \"Unix Makefiles\" or \"Ninja\".")
7+
endif()
8+
9+
project(projectM_SDL)
10+
11+
set(CMAKE_CXX_STANDARD 14)
12+
set(CMAKE_CXX_STANDARD_REQUIRED YES)
13+
set(CMAKE_POSITION_INDEPENDENT_CODE YES)
14+
15+
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
16+
17+
project(projectMSDL
18+
LANGUAGES C CXX
19+
VERSION 2.0.0
20+
)
21+
22+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
23+
24+
set(PROJECTM_LINKAGE "shared" CACHE STRING "Set to either shared or static to specify how libprojectM should be linked. Defaults to shared.")
25+
set(SDL2_LINKAGE "shared" CACHE STRING "Set to either shared or static to specify how libSDL2 should be linked. Defaults to shared.")
26+
27+
if(NOT PROJECTM_LINKAGE STREQUAL "shared" AND NOT PROJECTM_LINKAGE STREQUAL "static")
28+
message(FATAL_ERROR "Invalid libprojectM linkage provided in PROJECTM_LINKAGE: \"${PROJECTM_LINKAGE}\".\n"
29+
"Please specify either \"shared\" or \"static\"."
30+
)
31+
endif()
32+
33+
if(NOT SDL2_LINKAGE STREQUAL "shared" AND NOT SDL2_LINKAGE STREQUAL "static")
34+
message(FATAL_ERROR "Invalid libSDL2 linkage provided in SDL2_LINKAGE: \"${SDL2_LINKAGE}\".\n"
35+
"Please specify either \"shared\" or \"static\"."
36+
)
37+
endif()
38+
39+
find_package(libprojectM REQUIRED)
40+
find_package(SDL2 REQUIRED)
41+
find_package(Poco REQUIRED COMPONENTS Util)
42+
43+
if(SDL2_VERSION VERSION_LESS 2.0.5)
44+
message(FATAL_ERROR "libSDL version 2.0.5 or higher is required. Version found: ${SDL2_VERSION}.")
45+
endif()
46+
47+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND SDL2_VERSION VERSION_LESS 2.0.16)
48+
message(AUTHOR_WARNING
49+
"NOTE: libSDL 2.0.15 and lower do not support capture from PulseAudio \"monitor\" devices.\n"
50+
"It is highly recommended to use at least version 2.0.16!"
51+
)
52+
endif()
53+
54+
add_subdirectory(src)
55+
56+
if(ENABLE_TESTING)
57+
add_subdirectory(test)
58+
endif()
59+
60+
include(install.cmake)
61+
include(packaging.cmake)
62+
63+
message(STATUS "SDL version: ${SDL2_VERSION}")
64+
message(STATUS "Poco version: ${Poco_VERSION}")
65+
message(STATUS "projectM version: ${libprojectM_VERSION}")

LICENSE.md

+675
Large diffs are not rendered by default.

README.md

Whitespace-only changes.

cmake/SDL2Target.cmake

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Helper script to add the SDL2 CMake target and version variable as introduced in SDL 2.0.12.
2+
# Also fixes a wrong include path provided by the SDL2 config script.
3+
4+
5+
# Proper CMake target support was added in SDL 2.0.12, create one
6+
# Need to search again to find the full path of libSDL2
7+
if(NOT TARGET SDL2::SDL2)
8+
# Remove -lSDL2 as that is handled by CMake, note the space at the end so it does not replace e.g. -lSDL2main
9+
# This may require "libdir" being set (from above)
10+
string(REPLACE "-lSDL2 " "" SDL2_EXTRA_LINK_FLAGS " -lSDL2 ")
11+
string(STRIP "${SDL2_EXTRA_LINK_FLAGS}" SDL2_EXTRA_LINK_FLAGS)
12+
string(REPLACE "-lSDL2 " "" SDL2_EXTRA_LINK_FLAGS_STATIC " -Wl,--no-undefined -lm -ldl -lasound -lm -ldl -lpthread -lpulse-simple -lpulse -lX11 -lXext -lXcursor -lXinerama -lXi -lXrandr -lXss -lXxf86vm -lpthread -lrt ")
13+
string(STRIP "${SDL2_EXTRA_LINK_FLAGS_STATIC}" SDL2_EXTRA_LINK_FLAGS_STATIC)
14+
15+
find_library(SDL2_LIBRARY SDL2)
16+
if(NOT SDL2_LIBRARY)
17+
message(FATAL_ERROR "Could not determine the location of the SDL2 library.")
18+
endif()
19+
20+
add_library(SDL2::SDL2 SHARED IMPORTED)
21+
set_target_properties(SDL2::SDL2 PROPERTIES
22+
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}"
23+
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
24+
IMPORTED_LOCATION "${SDL2_LIBRARY}"
25+
INTERFACE_LINK_LIBRARIES "${SDL2_EXTRA_LINK_FLAGS}")
26+
27+
find_library(SDL2MAIN_LIBRARY SDL2main)
28+
if(NOT SDL2MAIN_LIBRARY)
29+
message(FATAL_ERROR "Could not determine the location of the SDL2main library.")
30+
endif()
31+
32+
add_library(SDL2::SDL2main STATIC IMPORTED)
33+
set_target_properties(SDL2::SDL2main PROPERTIES
34+
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
35+
IMPORTED_LOCATION "${SDL2MAIN_LIBRARY}")
36+
37+
# Retrieve the version from the SDL2_version.h header
38+
if(SDL2_INCLUDE_DIRS AND EXISTS "${SDL2_INCLUDE_DIRS}/SDL_version.h")
39+
file(STRINGS "${SDL2_INCLUDE_DIRS}/SDL_version.h" SDL_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$")
40+
file(STRINGS "${SDL2_INCLUDE_DIRS}/SDL_version.h" SDL_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$")
41+
file(STRINGS "${SDL2_INCLUDE_DIRS}/SDL_version.h" SDL_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$")
42+
string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL_VERSION_MAJOR "${SDL_VERSION_MAJOR_LINE}")
43+
string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL_VERSION_MINOR "${SDL_VERSION_MINOR_LINE}")
44+
string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL_VERSION_PATCH "${SDL_VERSION_PATCH_LINE}")
45+
set(SDL2_VERSION ${SDL_VERSION_MAJOR}.${SDL_VERSION_MINOR}.${SDL_VERSION_PATCH})
46+
unset(SDL_VERSION_MAJOR_LINE)
47+
unset(SDL_VERSION_MINOR_LINE)
48+
unset(SDL_VERSION_PATCH_LINE)
49+
unset(SDL_VERSION_MAJOR)
50+
unset(SDL_VERSION_MINOR)
51+
unset(SDL_VERSION_PATCH)
52+
endif()
53+
54+
endif()
55+
56+
# Temporary fix to deal with wrong include dir set by SDL2's CMake configuration.
57+
get_target_property(_SDL2_INCLUDE_DIR SDL2::SDL2 INTERFACE_INCLUDE_DIRECTORIES)
58+
if(_SDL2_INCLUDE_DIR MATCHES "(.+)/SDL2\$")
59+
message(STATUS "SDL2 include dir contains \"SDL2\" subdir (SDL bug #4004) - fixing to \"${CMAKE_MATCH_1}\".")
60+
set_target_properties(SDL2::SDL2 PROPERTIES
61+
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_MATCH_1}"
62+
)
63+
endif()
64+
65+
if(SDL2_VERSION AND SDL2_VERSION VERSION_LESS "2.0.5")
66+
message(FATAL_ERROR "SDL2 libraries were found, but have version ${SDL2_VERSION}. At least version 2.0.5 is required.")
67+
endif()
68+

install.cmake

Whitespace-only changes.

packaging.cmake

Whitespace-only changes.

src/AudioCapture.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "AudioCapture.h"
2+
3+
const char* AudioCapture::name() const
4+
{
5+
return "Audio Capturing";
6+
}
7+
8+
void AudioCapture::initialize(Poco::Util::Application& app)
9+
{
10+
_impl = std::make_unique<AudioCaptureImpl>();
11+
}
12+
13+
void AudioCapture::uninitialize()
14+
{
15+
_impl.reset();
16+
}

src/AudioCapture.h

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include AUDIO_IMPL_INCLUDE
4+
5+
#include <Poco/Util/Subsystem.h>
6+
7+
#include <memory>
8+
9+
class AudioCapture : public Poco::Util::Subsystem
10+
{
11+
public:
12+
const char* name() const override;
13+
14+
protected:
15+
void initialize(Poco::Util::Application& app) override;
16+
17+
void uninitialize() override;
18+
19+
std::unique_ptr<AudioCaptureImpl> _impl;
20+
};
21+
22+

src/AudioCaptureImpl_SDL.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "AudioCaptureImpl_SDL.h"

src/AudioCaptureImpl_SDL.h

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
/**
4+
* @brief SDL-based audio capturing thread.
5+
*
6+
* Uses SDL's audio API to capture PCM data from any supported drivers.
7+
*/
8+
class AudioCaptureImpl
9+
{
10+
11+
};
12+
13+

src/AudioCaptureImpl_WASAPI.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "AudioCaptureImpl_WASAPI.h"

src/AudioCaptureImpl_WASAPI.h

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
/**
4+
* @brief WASAPI-based audio capturing thread.
5+
*
6+
* Uses the Windows Audio Session API to capture PCM data from either a loopback device or
7+
* any pother available input device.
8+
*
9+
* The loopback device is always considered as the "first" available device. All other external audio
10+
* sources come after that.
11+
*/
12+
class AudioCaptureImpl
13+
{
14+
15+
};
16+
17+

src/CMakeLists.txt

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
add_executable(projectMSDL
2+
AudioCapture.cpp
3+
AudioCapture.h
4+
AudioCaptureImpl_SDL.cpp
5+
AudioCaptureImpl_SDL.h
6+
AudioCaptureImpl_WASAPI.cpp
7+
AudioCaptureImpl_WASAPI.h
8+
ProjectMSDLApplication.cpp
9+
ProjectMSDLApplication.h
10+
ProjectMWrapper.cpp
11+
ProjectMWrapper.h
12+
SDLRenderingWindow.h
13+
SDLRenderingWindow.cpp
14+
)
15+
16+
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
17+
target_sources(projectMSDL
18+
PRIVATE
19+
AudioCaptureImpl_WASAPI.h
20+
AudioCaptureImpl_WASAPI.cpp
21+
)
22+
target_compile_definitions(projectMSDL
23+
PRIVATE
24+
AUDIO_IMPL_INCLUDE="AudioCaptureImpl_WASAPI.h"
25+
)
26+
else()
27+
target_sources(projectMSDL
28+
PRIVATE
29+
AudioCaptureImpl_SDL.h
30+
AudioCaptureImpl_SDL.cpp
31+
)
32+
target_compile_definitions(projectMSDL
33+
PRIVATE
34+
AUDIO_IMPL_INCLUDE="AudioCaptureImpl_SDL.h"
35+
)
36+
endif()
37+
38+
39+
target_link_libraries(projectMSDL
40+
PRIVATE
41+
libprojectM::${PROJECTM_LINKAGE}
42+
Poco::Util
43+
SDL2::SDL2$<$<STREQUAL:"${SDL2_LINKAGE}","static">:"-static">
44+
)

src/ProjectMSDLApplication.cpp

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include "ProjectMSDLApplication.h"
2+
3+
#include "AudioCapture.h"
4+
#include "ProjectMWrapper.h"
5+
#include "SDLRenderingWindow.h"
6+
7+
#include <Poco/Environment.h>
8+
#include <Poco/File.h>
9+
10+
ProjectMSDLApplication::ProjectMSDLApplication()
11+
{
12+
// Note: order here is important, as subsystems are initialized in the same order.
13+
addSubsystem(new SDLRenderingWindow);
14+
addSubsystem(new ProjectMWrapper);
15+
addSubsystem(new AudioCapture);
16+
}
17+
18+
const char* ProjectMSDLApplication::name() const
19+
{
20+
return "projectMSDL";
21+
}
22+
23+
void ProjectMSDLApplication::initialize(Poco::Util::Application& self)
24+
{
25+
loadConfiguration(PRIO_DEFAULT);
26+
27+
// Try to load user's custom configuration file on top.
28+
Poco::Path userConfigurationFile = Poco::Path::configHome() + "projectM" + Poco::Path::separator() + "projectMSDL.properties";
29+
if (Poco::File(userConfigurationFile).exists())
30+
{
31+
loadConfiguration(userConfigurationFile.toString(), -10);
32+
}
33+
34+
Application::initialize(self);
35+
}
36+
37+
void ProjectMSDLApplication::uninitialize()
38+
{
39+
Application::uninitialize();
40+
}
41+
42+
void ProjectMSDLApplication::defineOptions(Poco::Util::OptionSet& options)
43+
{
44+
45+
}
46+
47+
int ProjectMSDLApplication::main(const std::vector<std::string>& args)
48+
{
49+
return EXIT_SUCCESS;
50+
}
51+
52+
POCO_APP_MAIN(ProjectMSDLApplication)

src/ProjectMSDLApplication.h

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include <Poco/Util/Application.h>
4+
5+
class ProjectMSDLApplication : public Poco::Util::Application
6+
{
7+
public:
8+
ProjectMSDLApplication();
9+
10+
const char* name() const override;
11+
12+
protected:
13+
void initialize(Application& self) override;
14+
15+
void uninitialize() override;
16+
17+
void defineOptions(Poco::Util::OptionSet& options) override;
18+
19+
int main(const std::vector<std::string>& args) override;
20+
};
21+
22+

src/ProjectMWrapper.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "ProjectMWrapper.h"
2+
3+
const char* ProjectMWrapper::name() const
4+
{
5+
return "ProjectM Wrapper";
6+
}
7+
8+
void ProjectMWrapper::initialize(Poco::Util::Application& app)
9+
{
10+
if (!_projectM)
11+
{
12+
projectm_create_settings(nullptr, PROJECTM_FLAG_NONE);
13+
}
14+
}
15+
16+
void ProjectMWrapper::uninitialize()
17+
{
18+
if (_projectM)
19+
{
20+
projectm_destroy(_projectM);
21+
_projectM = nullptr;
22+
}
23+
}
24+
25+
projectm* ProjectMWrapper::ProjectM() const
26+
{
27+
return _projectM;
28+
}

src/ProjectMWrapper.h

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
#include <libprojectM/projectM.h>
4+
5+
#include <Poco/Util/Subsystem.h>
6+
7+
class ProjectMWrapper : public Poco::Util::Subsystem
8+
{
9+
public:
10+
const char* name() const override;
11+
12+
/**
13+
* Returns the projectM instance handle.
14+
* @return The projectM instance handle used to call API functions.
15+
*/
16+
projectm* ProjectM() const;
17+
18+
protected:
19+
void initialize(Poco::Util::Application& app) override;
20+
21+
void uninitialize() override;
22+
23+
projectm* _projectM{ nullptr };
24+
};
25+
26+

0 commit comments

Comments
 (0)