Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support #479

Closed
karlstav opened this issue Nov 17, 2022 · 26 comments
Closed

Windows support #479

karlstav opened this issue Nov 17, 2022 · 26 comments

Comments

@karlstav
Copy link
Owner

since we now has sdl support and this ting exists I thought that windows support should be simple to implement. And it was!

so @quantum5 hope you don't mind that I snipped your winscap code to create the input module.

windows does not like autoconf so I made a separate visual studio solution for it. It all lives in it's own branch for now (just check out windows branch), but it will be merged to master soon. Both normal sdl and the new sgl_glsl works fine:

cava

@quantum5
Copy link
Contributor

Sure, I don't mind that you copied winscap, but I would strongly recommend that you rewrite it anyways. I wrote winscap in like an hour or two, lazily using the builtin Visual C++ smart pointer library and C++ for no reason other than to make it quicker to code. It seems like you replaced the smart pointer code with plain COM code but didn't do any of the cleanups, so right now cava is leaking memory like a sieve on Windows.

You can write COM code perfectly fine in C, so I would recommend that you just do the rewrite and eliminate the C++ dependency, fixing the memory management in the process.

@karlstav
Copy link
Owner Author

Alright, my first thought was to take it down to plain c, but I don't have any experience with com. So when I couldn't make it work my second thought was that it had to be in c++. But if I can do it all in c that's a lot better, will do that. Thanks!

karlstav pushed a commit that referenced this issue Nov 20, 2022
karlstav added a commit that referenced this issue Nov 28, 2022
This is a large commit that most likely should have been splitted
up a bit. But poor workflow made it better to just squash together
all work from the windows branch.

in short:

1) added windows input module (winscap, originaly written by @quantum5)
2) visual studio solution and proejct file added in cava_win folder
   this uses nuget to get all dependencies and all paths should be set
   up to use them autmatically
3) some non-windows stuff are ifdefed out, this might be seperated out in
   to other files at a later time
4) a common input sample separator was added in the common
   write_to_cava_input_buffers function. This required all of the other
   input modules to be re-written slightly. All in all it should be less
   duplicated code now
5) since ini files are native to windows the config loading part is more or
   less separated. Should maybe be better separated.

stuff that are not supported on windows:

1) terminal output
2) raw output
2) embedding the default config file into the binary
3) user eq
@karlstav karlstav closed this as completed Jan 8, 2023
@rashil2000
Copy link

rashil2000 commented Jan 25, 2023

Hey @karlstav! I was able to build cava from source on Windows and both sdl and sdl_glsl outputs are working 💖

However since cava is popularly used in terminals, how can I use the ncurses or notcurses output?

(ncurses is available in the MSYS2 environment, see https://packages.msys2.org/base/mingw-w64-ncurses. Notcurses, while not readily available, can also be built inside the MSYS2 environment, see https://github.com/dankamongmen/notcurses/blob/master/INSTALL.md#microsoft-windows)

@karlstav
Copy link
Owner Author

Terminal output should be possible, will require some rewriting as it still relies on some unix based stuff.

I will try to stay clear of the msys2 as I have more gone down the route of visual studio / msbuild. (If people want to emulate unix/bash they might as well run cava via WSL).

However, the noncurses implementation that i use in cava is something i wrote myself and only uses printf so it should be possible to port to windows. I will have a go at it when I get time.

@rashil2000
Copy link

Just as a heads up, the MSYS2 environment I mentioned above is only for building: it does not emulate unix - I linked to the mingw variants of the ncurses and notcurses packages - which is pure Win32 stuff.

@karlstav
Copy link
Owner Author

hi @rashil2000,

I was able to make the noncurses output work! There was however two issues that might come back to bite us:

  1. I had to force on utf8 by setting locale to "en_US.utf8". this must be installed on the system for things to work,
  2. printing to stdout in windows is painfully slow, I added a calculation of the time delta and used the fps sleep timer to sync things. In large terminal windows it will however still be slow.

@rashil2000
Copy link

It looks great!

I was curious about the build system here and tried to get the ncurses part working. I added the relevant file in the project file:

diff --git a/cava_win/cava/cava.vcxproj b/cava_win/cava/cava.vcxproj
index d158fca..8687e76 100644
--- a/cava_win/cava/cava.vcxproj
+++ b/cava_win/cava/cava.vcxproj
@@ -153,6 +153,7 @@
     <ClCompile Include="..\..\output\sdl_cava.c" />
     <ClCompile Include="..\..\output\sdl_glsl.c" />
     <ClCompile Include="..\..\output\terminal_noncurses.c" />
+    <ClCompile Include="..\..\output\terminal_ncurses.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\cavacore.h" />
@@ -163,6 +164,7 @@
     <ClInclude Include="..\..\output\sdl_cava.h" />
     <ClInclude Include="..\..\output\sdl_glsl.h" />
     <ClInclude Include="..\..\output\terminal_noncurses.h" />
+    <ClInclude Include="..\..\output\terminal_ncurses.h" />
     <ClInclude Include="..\..\util.h" />
   </ItemGroup>
   <ItemGroup>

I downloaded the ncurses package, and added an include path in the build command:

msbuild /p:IncludePath="D:\Downloads\mingw-w64-x86_64-ncurses\mingw64\include;D:\Downloads\mingw-w64-x86_64-ncurses\mingw64\include\ncursesw;$(IncludePath)"

But now I'm facing some bogus syntax errors:

image

What seems to be the issue here?

@karlstav
Copy link
Owner Author

msvc does not like that you use variables in array length, just replace gradient_count with 8 here:

short unsigned int rgb[2 * gradient_count - 1][3];

@rashil2000
Copy link

Hmm, that fixes error on line 130, but I still can't figure out what's wrong with 252, 257 etc.

@karlstav
Copy link
Owner Author

Looks like it's the max macro in util.h that's causing issues.

@karlstav
Copy link
Owner Author

looks like the max macro is already defined on windows. I just ifdefed it out. try now.

@rashil2000
Copy link

The compiler errors are gone but there are linking errors now...

image

@karlstav
Copy link
Owner Author

doesn't look like you are linking the ncurses library at all. I think you might have to add it here:

<AdditionalDependencies>opengl32.lib;$(SolutionDir)\packages\glew.1.9.0.1\build\native\lib\v110\x64\Release\dynamic\glew.lib;$(SolutionDir)\packages\pthreads.2.9.1.4\build\native\lib\v110\x64\Release\dynamic\cdecl\libpthread.lib;%(AdditionalDependencies)</AdditionalDependencies>

remember to add them for both debug and release.

karlstav pushed a commit that referenced this issue Jan 31, 2023
remove hard coded not used include paths, use dependencies debug libs in debug
@rashil2000
Copy link

Okay, I added it. Compilation successful! I changed the config file to use ncurses output but it threw this error :(

cava/config.c

Line 205 in a16742a

write_errorf(error, "cava was built without ncurses support, install ncursesw dev files "

@karlstav
Copy link
Owner Author

karlstav commented Feb 1, 2023

You have to set the NCURSES preprocessor define in the project file

@rashil2000
Copy link

Well, I got this far...

fprintf(stderr, "Your terminal can not change color definitions, "

@karlstav
Copy link
Owner Author

karlstav commented Feb 1, 2023

hmm, windows terminal is able to change color definitions (at least it does this in noncurses mode). However the default color should be not to try to do this. I changed it to that now. So try again after latest commit or just set foreground and background colors in your config to "default"

@rashil2000
Copy link

Now it starts up and exits immediately, no error shown.

@karlstav
Copy link
Owner Author

karlstav commented Feb 2, 2023

my bad @rashil2000, fixed now. Please try again.

@rashil2000
Copy link

Yes! It's working now.

I had to disable gradients in the config file (because of the complaint with changing terminal colors), and then it started working.

The performance is much much better than nonurses.

I can make a PR for this change, but since I'm using MinGW's ncurses package, I don't exactly know how to proceed. I searched around on nuget.org and found these wrappers:

Should we use one of these?

Also, currently it's only black-and-white, but I know for a fact that ncurses can change Windows terminal's colors - the cmatrix project uses ncurses and it supports all colors, even bold texts.

@karlstav
Copy link
Owner Author

karlstav commented Feb 2, 2023

Nice!

You could try to just comment or ifdef out the check for "can change color".

I don't want to have ncurses enabled by default unless it can be installed via the nuget thing. If there is no way of doing that we will have to stick with a guide in the readme on how to install and build with ncurses.

@rashil2000
Copy link

You could try to just comment or ifdef out the check for "can change color".

I temporarily removed the check, but the colors still stay black-and-white :(

@karlstav
Copy link
Owner Author

karlstav commented Feb 2, 2023

What if you set the foreground color to a predefined color like "red"? Remember to disable gradient first.

@rashil2000
Copy link

No effect :(

@rashil2000
Copy link

I made some changes to build cava using the MinGW compiler (basically the commands mentioned in the linux section of Readme):

diff --git a/Makefile.am b/Makefile.am
index f133e95..b6cb4de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,13 +3,19 @@ AUTOMAKE_OPTIONS = foreign
 ACLOCAL_AMFLAGS = -I m4
 
 bin_PROGRAMS = cava
-cava_SOURCES = cava.c cavacore.c config.c input/common.c input/fifo.c input/shmem.c \
+cava_SOURCES = cava.c cavacore.c config.c input/common.c \
                output/terminal_noncurses.c output/raw.c output/noritake.c
 cava_CPPFLAGS = -DPACKAGE=\"$(PACKAGE)\" -DVERSION=\"$(VERSION)\" \
            -D_POSIX_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE_EXTENDED \
 	   -DFONTDIR=\"@FONT_DIR@\"
 cava_CFLAGS = -std=c99 -Wall -Wextra -Wno-unused-result -Wno-unknown-warning-option -Wno-maybe-uninitialized -Wno-vla-parameter
 
+if WINDOWS
+    cava_SOURCES += input/winscap.c
+    cava_CFLAGS += -lkernel32 -lole32
+else
+    cava_SOURCES += input/fifo.c
+    cava_SOURCES += input/shmem.c
 if OSX
     cava_CFLAGS += -DNORT
     cava_LDADD =
@@ -18,6 +24,7 @@ else
     cava_font_dir = @FONT_DIR@
     cava_font__DATA = cava.psf
 endif
+endif
 
 if ALSA
     cava_SOURCES += input/alsa.c
diff --git a/cava.c b/cava.c
index c146682..a73fd8e 100644
--- a/cava.c
+++ b/cava.c
@@ -97,7 +97,7 @@ int should_quit = 0;
 // these variables are used only in main, but making them global
 // will allow us to not free them on exit without ASan complaining
 struct config_params p;
-
+#undef SDL
 // general: cleanup
 void cleanup(void) {
     if (output_mode == OUTPUT_NCURSES) {
diff --git a/config.c b/config.c
index a978264..e160936 100644
--- a/config.c
+++ b/config.c
@@ -19,6 +19,7 @@
 #define NUMBER_OF_SHADERS 2
 
 #ifdef _MSC_VER
+#define mkdir(A, B) mkdir(A)
 #include "Windows.h"
 #define PATH_MAX 260
 #define PACKAGE "cava"
diff --git a/configure.ac b/configure.ac
index 9a8b0e7..fe49d55 100644
--- a/configure.ac
+++ b/configure.ac
@@ -212,7 +212,7 @@ AC_CHECK_LIB(SDL2,SDL_Init, have_sdl=yes, have_sdl=no)
           [do not include support for output with sdl_glsl])
       )
       AS_IF([test "x$enable_output_sdl_glsl" != "xno"], [
-      AX_CHECK_GL(have_opengl=yes, have_opengl=no)
+      have_opengl=yes
       if [[ $have_opengl = "yes" ]] ; then
         LIBS="$LIBS $GL_LIBS"
         CPPFLAGS="$CPPFLAGS -DSDL_GLSL $GL_CFLAGS"
@@ -321,6 +321,11 @@ case "${host_os}" in
         AC_MSG_NOTICE([OSX detected])
         build_mac=yes
         ;;
+    mingw*)
+        AC_MSG_NOTICE([Windows detected])
+        AC_DEFINE([_MSC_VER])
+        build_windows=yes
+        ;;
     freebsd*)
         AC_MSG_NOTICE([FreeBSD detected])
         build_linux=yes
@@ -332,6 +337,7 @@ esac
 
 # Pass the conditionals to automake
 AM_CONDITIONAL([LINUX], [test "$build_linux" = "yes"])
+AM_CONDITIONAL([WINDOWS], [test "$build_windows" = "yes"])
 AM_CONDITIONAL([OSX], [test "$build_mac" = "yes"])
 
 
diff --git a/input/winscap.c b/input/winscap.c
index 8738ec9..1c79e06 100644
--- a/input/winscap.c
+++ b/input/winscap.c
@@ -18,6 +18,15 @@
 #define REFTIMES_PER_SEC 10000000
 #define REFTIMES_PER_MILLISEC 10000
 
+#ifndef PKEY_Device_FriendlyName
+
+#undef DEFINE_PROPERTYKEY
+#define DEFINE_PROPERTYKEY(id, a, b, c, d, e, f, g, h, i, j, k, l) \
+	const PROPERTYKEY id = { { a, b, c, { d, e, f, g, h, i, j, k, } }, l };
+
+DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
+#endif
+
 // the device change funcitonality is disabled until I figure out how
 // or if to rewrite it to c
 /*
diff --git a/output/terminal_ncurses.c b/output/terminal_ncurses.c
index 7058714..8b50b96 100644
--- a/output/terminal_ncurses.c
+++ b/output/terminal_ncurses.c
@@ -6,6 +6,9 @@
 #include <wchar.h>
 
 #include "util.h"
+#ifdef _MSC_VER
+#include <windows.h>
+#endif
 
 int gradient_size = 64;
 
@@ -310,6 +313,17 @@ int draw_terminal_ncurses(int is_tty, int dimension_value, int dimension_bar, in
 
 // general: cleanup
 void cleanup_terminal_ncurses(void) {
+#ifdef _MSC_VER
+    setecho(1, 1);
+    HANDLE hStdOut = NULL;
+    CONSOLE_CURSOR_INFO curInfo;
+
+    hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+    GetConsoleCursorInfo(hStdOut, &curInfo);
+    curInfo.bVisible = TRUE;
+    SetConsoleCursorInfo(hStdOut, &curInfo);
+    system("cls");
+#else
     echo();
     system("setfont  >/dev/null 2>&1");
     system("setfont /usr/share/consolefonts/Lat2-Fixed16.psf.gz  >/dev/null 2>&1");
@@ -326,4 +340,5 @@ void cleanup_terminal_ncurses(void) {
     standend();
     endwin();
     system("clear");
+#endif
 }

But I face a huge wall of errors when running make. I don't think they're syntax/semantic errors, they're just redefinition errors:
image

How should I fix this?

@aetonsi
Copy link

aetonsi commented Jul 3, 2023

Hi everyone, i just tried to get cava running on win11, with no luck.
If i build cava_win.sln while being in the master branch, no errors, lots of warnings, build succeeds. But when i try to execute the file, it exits with code -1073741515.
If i build the solution while in the windows branch, lots of errors and it does not compile.
I think it's a DLL problem. I see it mentioned in the INSTALL/README but i don't understand what i have to do.
Can someone point me in the right direction?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants