Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions src/musializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
#endif // _WIN32

#include "./hotreload.h"
#include "./thirdparty/nob.h"

int main(void)
int main(int argc, char **argv)
{
#ifndef _WIN32
// NOTE: This is needed because if the pipe between Musializer and FFmpeg breaks
Expand All @@ -24,7 +25,53 @@ int main(void)
#endif // _WIN32

if (!reload_libplug()) return 1;

nob_shift(argv, argc);
bool isCLI = argc > 0;
char *input_path = NULL;
char *render_path = NULL;
bool cli_rendering = false;
Nob_File_Paths input_paths = {0};
if (isCLI)
{
const char *command_name = nob_shift(argv, argc);
if (strcmp(command_name, "--render") == 0 || strcmp(command_name, "-r") == 0)
{
cli_rendering = true;
input_path = argc > 0 ? nob_shift(argv, argc) : NULL;
if (input_path == NULL)
{
nob_log(NOB_ERROR, "Error: No music file provided.");
return 1;
}
render_path = argc > 0 ? nob_shift(argv, argc) : NULL;
if (render_path == NULL)
{
char buffer[512];
snprintf(buffer, sizeof(buffer), "%s", input_path);
char *dot = strrchr(buffer, '.');
if (dot != NULL)
{
strcpy(dot, ".mp4");
}
else
{
strcat(buffer, ".mp4");
}
render_path = strdup(buffer);
}
nob_log(NOB_INFO, "Music path: %s", input_path);
nob_log(NOB_INFO, "Render path: %s", render_path);
}
else
{
nob_da_append(&input_paths, command_name);
while (argc > 0)
{
input_path = nob_shift(argv, argc);
nob_da_append(&input_paths, input_path);
}
}
}
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_ALWAYS_RUN);
size_t factor = 80;
InitWindow(factor*16, factor*9, "Musializer");
Expand All @@ -39,14 +86,19 @@ int main(void)
SetExitKey(KEY_NULL);
InitAudioDevice();

plug_init();
while (!WindowShouldClose()) {
if (IsKeyPressed(KEY_H)) {
void *state = plug_pre_reload();
if (!reload_libplug()) return 1;
plug_post_reload(state);
plug_init(&input_paths);
if (cli_rendering) {
plug_start_cli_rendering_track(input_path, render_path);
}
else {
while (!WindowShouldClose()) {
if (IsKeyPressed(KEY_H)) {
void *state = plug_pre_reload();
if (!reload_libplug()) return 1;
plug_post_reload(state);
}
plug_update();
}
plug_update();
}

CloseAudioDevice();
Expand Down
77 changes: 63 additions & 14 deletions src/plug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,25 @@ static bool toolbar(Track *track, Rectangle boundary)
return interacted;
}

static void add_track(const char *file_path)
{
Music music = LoadMusicStream(file_path);
if (IsMusicValid(music))
{
AttachAudioStreamProcessor(music.stream, callback);
char *file_path_copy = strdup(file_path);
assert(file_path_copy != NULL);
nob_da_append(&p->tracks, (CLITERAL(Track){
.file_path = file_path_copy,
.music = music,
}));
}
else
{
popup_tray_push(&p->pt);
}
}

static void preview_screen(void)
{
int w = GetScreenWidth();
Expand Down Expand Up @@ -1600,19 +1619,7 @@ static void preview_screen(void)
char const *filter_params[] = {"*.wav", "*.ogg", "*.mp3", "*.qoa", "*.xm", "*.mod", "*.flac"};
char *input_path = tinyfd_openFileDialog("Path to music file", "./", NOB_ARRAY_LEN(filter_params), filter_params, "music file", allow_multiple_selects);
if (input_path) {
Music music = LoadMusicStream(input_path);
if (IsMusicValid(music)) {
AttachAudioStreamProcessor(music.stream, callback);
char *file_path = strdup(input_path);
assert(file_path != NULL);
nob_da_append(&p->tracks, (CLITERAL(Track) {
.file_path = file_path,
.music = music,
}));
} else {
popup_tray_push(&p->pt);
}

add_track(input_path);
if (current_track() == NULL && p->tracks.count > 0) {
p->current_track = 0;
PlayMusicStream(p->tracks.items[0].music);
Expand Down Expand Up @@ -1862,7 +1869,7 @@ static void unload_assets()
}
}

MUSIALIZER_PLUG void plug_init(void)
MUSIALIZER_PLUG void plug_init(Nob_File_Paths *paths)
{
p = malloc(sizeof(*p));
assert(p != NULL && "Buy more RAM lol");
Expand All @@ -1871,6 +1878,15 @@ MUSIALIZER_PLUG void plug_init(void)
load_assets();
p->screen = LoadRenderTexture(RENDER_WIDTH, RENDER_HEIGHT);
p->current_track = -1;
da_foreach(const char *, i, paths)
{
add_track(*i);
if (current_track() == NULL && p->tracks.count > 0)
{
p->current_track = 0;
PlayMusicStream(p->tracks.items[0].music);
}
}

// TODO: restore master volume between sessions
SetMasterVolume(0.5);
Expand Down Expand Up @@ -1923,6 +1939,39 @@ MUSIALIZER_PLUG void plug_update(void)
EndDrawing();
}

MUSIALIZER_PLUG void plug_start_cli_rendering_track(const char *input_path, const char *output_path)
{
if (input_path == NULL || output_path == NULL)
return;
Music music = LoadMusicStream(input_path);
if (!IsMusicValid(music))
return;
AttachAudioStreamProcessor(music.stream, callback);
char *file_path = strdup(input_path);
assert(file_path != NULL);
nob_da_append(&p->tracks, (CLITERAL(Track){
.file_path = file_path,
.music = music,
}));
p->current_track = 0;
fft_clean();
// TODO: LoadWave is pretty slow on big files
p->wave = LoadWave(input_path);
p->wave_cursor = 0;
p->wave_samples = LoadWaveSamples(p->wave);
// TODO: set the rendering output path based on the input path
// Basically output into the same folder
p->ffmpeg = ffmpeg_start_rendering(output_path, p->screen.texture.width, p->screen.texture.height, RENDER_FPS, input_path);
SetTargetFPS(0);
p->rendering = true;
p->cancel_rendering = false;
SetTraceLogLevel(LOG_WARNING);
while (p->rendering)
{
plug_update();
}
}

// TODO: About Page that includes current commit, version and the platforms
// We may also include licenses and contributors there.
// TODO: Actual Fullscreen Mode
Expand Down
8 changes: 6 additions & 2 deletions src/plug.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
#ifndef PLUG_H_
#define PLUG_H_

#define NOB_STRIP_PREFIX
#include "thirdparty/nob.h"

#define LIST_OF_PLUGS \
PLUG(plug_init, void, void) \
PLUG(plug_init, void, Nob_File_Paths*) \
PLUG(plug_pre_reload, void*, void) \
PLUG(plug_post_reload, void, void*) \
PLUG(plug_load_resource, void*, const char*, size_t*) \
PLUG(plug_free_resource, void, void*) \
PLUG(plug_update, void, void)
PLUG(plug_update, void, void) \
PLUG(plug_start_cli_rendering_track, void, const char *, const char *)

#define PLUG(name, ret, ...) typedef ret (name##_t)(__VA_ARGS__);
LIST_OF_PLUGS
Expand Down