From 94150cef70a377cf94d4524b4634848af8a25251 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 15 Apr 2015 13:37:38 +0200 Subject: [PATCH] Add 'Record Driver' option --- Makefile.common | 1 + config.def.h | 9 +++ configuration.c | 17 +++++ configuration.h | 7 ++ driver.c | 6 ++ driver.h | 2 +- griffin/griffin.c | 1 + record/drivers/ffmpeg.c | 2 +- record/drivers/record_null.c | 62 ++++++++++++++++++ record/record_driver.c | 122 ++++++++++++++++++++++++++++++++--- record/record_driver.h | 39 +++++++++-- settings.c | 11 ++++ 12 files changed, 261 insertions(+), 18 deletions(-) create mode 100644 record/drivers/record_null.c diff --git a/Makefile.common b/Makefile.common index b6579d75aa..c130add104 100644 --- a/Makefile.common +++ b/Makefile.common @@ -172,6 +172,7 @@ OBJ += frontend/frontend.o \ playlist.o \ movie.o \ record/record_driver.o \ + record/drivers/record_null.o \ performance.o diff --git a/config.def.h b/config.def.h index c0aa4a5a86..8ad7417bd3 100644 --- a/config.def.h +++ b/config.def.h @@ -126,6 +126,9 @@ enum MENU_RMENU_XUI, MENU_GLUI, MENU_XMB, + + RECORD_FFMPEG, + RECORD_NULL, }; #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__) @@ -210,6 +213,12 @@ enum #define AUDIO_DEFAULT_RESAMPLER_DRIVER AUDIO_RESAMPLER_SINC #endif +#if defined(HAVE_FFMPEG) +#define RECORD_DEFAULT_DRIVER RECORD_FFMPEG +#else +#define RECORD_DEFAULT_DRIVER RECORD_NULL +#endif + #if defined(XENON) #define INPUT_DEFAULT_DRIVER INPUT_XENON360 #elif defined(_XBOX360) || defined(_XBOX) || defined(HAVE_XINPUT2) || defined(HAVE_XINPUT_XBOX1) diff --git a/configuration.c b/configuration.c index 3099a4375c..68b9f888c7 100644 --- a/configuration.c +++ b/configuration.c @@ -124,6 +124,19 @@ const char *config_get_default_audio(void) return "null"; } +const char *config_get_default_record(void) +{ + switch (RECORD_DEFAULT_DRIVER) + { + case RECORD_FFMPEG: + return "ffmpeg"; + default: + break; + } + + return "null"; +} + /** * config_get_default_audio_resampler: * @@ -397,6 +410,7 @@ static void config_set_defaults(void) #endif const char *def_camera = config_get_default_camera(); const char *def_location = config_get_default_location(); + const char *def_record = config_get_default_record(); if (def_camera) strlcpy(settings->camera.driver, @@ -419,6 +433,9 @@ static void config_set_defaults(void) if (def_joypad) strlcpy(settings->input.joypad_driver, def_joypad, sizeof(settings->input.joypad_driver)); + if (def_record) + strlcpy(settings->record.driver, + def_record, sizeof(settings->record.driver)); #ifdef HAVE_MENU if (def_menu) strlcpy(settings->menu.driver, diff --git a/configuration.h b/configuration.h index 2f6c87513b..76dfb50e5c 100644 --- a/configuration.h +++ b/configuration.h @@ -92,6 +92,11 @@ typedef struct settings bool force_srgb_disable; } video; + struct + { + char driver[32]; + } record; + struct { bool menubar_enable; @@ -393,6 +398,8 @@ const char *config_get_default_joypad(void); const char *config_get_default_menu(void); #endif +const char *config_get_default_record(void); + /** * config_load: * diff --git a/driver.c b/driver.c index f2724047fa..755311e2e7 100644 --- a/driver.c +++ b/driver.c @@ -123,6 +123,12 @@ static const void *find_driver_nonempty(const char *label, int i, if (drv) strlcpy(str, audio_driver_find_ident(i), sizeof_str); } + else if (!strcmp(label, "record_driver")) + { + drv = record_driver_find_handle(i); + if (drv) + strlcpy(str, record_driver_find_ident(i), sizeof_str); + } else if (!strcmp(label, "audio_resampler_driver")) { drv = audio_resampler_driver_find_handle(i); diff --git a/driver.h b/driver.h index d2b8d6ca25..b1c319c53a 100644 --- a/driver.h +++ b/driver.h @@ -199,7 +199,7 @@ typedef struct driver const camera_driver_t *camera; const location_driver_t *location; const rarch_resampler_t *resampler; - const ffemu_backend_t *recording; + const record_driver_t *recording; struct retro_callbacks retro_ctx; void *audio_data; diff --git a/griffin/griffin.c b/griffin/griffin.c index db43a6e9df..26f342f79c 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -645,6 +645,7 @@ RECORDING ============================================================ */ #include "../movie.c" #include "../record/record_driver.c" +#include "../record/drivers/record_null.c" /*============================================================ THREAD diff --git a/record/drivers/ffmpeg.c b/record/drivers/ffmpeg.c index e632d4e22f..585d788468 100644 --- a/record/drivers/ffmpeg.c +++ b/record/drivers/ffmpeg.c @@ -1408,7 +1408,7 @@ static void ffmpeg_thread(void *data) av_free(audio_buf); } -const ffemu_backend_t ffemu_ffmpeg = { +const record_driver_t ffemu_ffmpeg = { ffmpeg_new, ffmpeg_free, ffmpeg_push_video, diff --git a/record/drivers/record_null.c b/record/drivers/record_null.c new file mode 100644 index 0000000000..252752cb80 --- /dev/null +++ b/record/drivers/record_null.c @@ -0,0 +1,62 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2015 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#include +#include +#include +#include +#include "../record_driver.h" + +static void record_null_free(void *data) +{ +} + +static void *record_null_new(const struct ffemu_params *params) +{ + return NULL; +} + +static bool record_null_push_video(void *data, + const struct ffemu_video_data *video_data) +{ + return false; +} + +static bool record_null_push_audio(void *data, + const struct ffemu_audio_data *audio_data) +{ + return false; +} + +static bool record_null_finalize(void *data) +{ + return false; +} + +const record_driver_t ffemu_null = { + record_null_new, + record_null_free, + record_null_push_video, + record_null_push_audio, + record_null_finalize, + "null", +}; diff --git a/record/record_driver.c b/record/record_driver.c index c6083c8e34..a0f880a517 100644 --- a/record/record_driver.c +++ b/record/record_driver.c @@ -31,13 +31,114 @@ #include "../config.h" #endif -static const ffemu_backend_t *ffemu_backends[] = { +static const record_driver_t *record_drivers[] = { #ifdef HAVE_FFMPEG &ffemu_ffmpeg, #endif + &ffemu_null, NULL, }; +/** + * record_driver_find_ident: + * @idx : index of driver to get handle to. + * + * Returns: Human-readable identifier of record driver at index. Can be NULL + * if nothing found. + **/ +const char *record_driver_find_ident(int idx) +{ + const record_driver_t *drv = record_drivers[idx]; + if (!drv) + return NULL; + return drv->ident; +} + +/** + * record_driver_find_handle: + * @idx : index of driver to get handle to. + * + * Returns: handle to record driver at index. Can be NULL + * if nothing found. + **/ +const void *record_driver_find_handle(int idx) +{ + const void *drv = record_drivers[idx]; + if (!drv) + return NULL; + return drv; +} + +/** + * config_get_record_driver_options: + * + * Get an enumerated list of all record driver names, separated by '|'. + * + * Returns: string listing of all record driver names, separated by '|'. + **/ +const char* config_get_record_driver_options(void) +{ + union string_list_elem_attr attr; + unsigned i; + char *options = NULL; + int options_len = 0; + struct string_list *options_l = string_list_new(); + + attr.i = 0; + + if (!options_l) + return NULL; + + for (i = 0; record_driver_find_handle(i); i++) + { + const char *opt = record_driver_find_ident(i); + options_len += strlen(opt) + 1; + string_list_append(options_l, opt, attr); + } + + options = (char*)calloc(options_len, sizeof(char)); + + if (!options) + { + string_list_free(options_l); + options_l = NULL; + return NULL; + } + + string_list_join_concat(options, options_len, options_l, "|"); + + string_list_free(options_l); + options_l = NULL; + + return options; +} + +void find_record_driver(void) +{ + driver_t *driver = driver_get_ptr(); + settings_t *settings = config_get_ptr(); + + int i = find_driver_index("record_driver", settings->record.driver); + + if (i >= 0) + driver->recording = (const record_driver_t*)audio_driver_find_handle(i); + else + { + unsigned d; + RARCH_ERR("Couldn't find any audio driver named \"%s\"\n", + settings->audio.driver); + RARCH_LOG_OUTPUT("Available audio drivers are:\n"); + for (d = 0; audio_driver_find_handle(d); d++) + RARCH_LOG_OUTPUT("\t%s\n", record_driver_find_ident(d)); + RARCH_WARN("Going to default to first audio driver...\n"); + + driver->audio = (const audio_driver_t*)audio_driver_find_handle(0); + + if (!driver->audio) + rarch_fail(1, "find_audio_driver()"); + } +} + /** * ffemu_find_backend: * @ident : Identifier of driver to find. @@ -47,19 +148,20 @@ static const ffemu_backend_t *ffemu_backends[] = { * Returns: recording driver handle if successful, otherwise * NULL. **/ -const ffemu_backend_t *ffemu_find_backend(const char *ident) +const record_driver_t *ffemu_find_backend(const char *ident) { unsigned i; - for (i = 0; ffemu_backends[i]; i++) + for (i = 0; record_drivers[i]; i++) { - if (!strcmp(ffemu_backends[i]->ident, ident)) - return ffemu_backends[i]; + if (!strcmp(record_drivers[i]->ident, ident)) + return record_drivers[i]; } return NULL; } + /** * gfx_ctx_init_first: * @backend : Recording backend handle. @@ -70,19 +172,19 @@ const ffemu_backend_t *ffemu_find_backend(const char *ident) * * Returns: true (1) if successful, otherwise false (0). **/ -bool ffemu_init_first(const ffemu_backend_t **backend, void **data, +bool record_driver_init_first(const record_driver_t **backend, void **data, const struct ffemu_params *params) { unsigned i; - for (i = 0; ffemu_backends[i]; i++) + for (i = 0; record_drivers[i]; i++) { - void *handle = ffemu_backends[i]->init(params); + void *handle = record_drivers[i]->init(params); if (!handle) continue; - *backend = ffemu_backends[i]; + *backend = record_drivers[i]; *data = handle; return true; } @@ -308,7 +410,7 @@ bool recording_init(void) params.fb_width, params.fb_height, (unsigned)params.pix_fmt); - if (!ffemu_init_first(&driver->recording, &driver->recording_data, ¶ms)) + if (!record_driver_init_first(&driver->recording, &driver->recording_data, ¶ms)) { RARCH_ERR(RETRO_LOG_INIT_RECORDING_FAILED); event_command(EVENT_CMD_GPU_RECORD_DEINIT); diff --git a/record/record_driver.h b/record/record_driver.h index 86c0caa657..54e5eb0f3f 100644 --- a/record/record_driver.h +++ b/record/record_driver.h @@ -13,7 +13,6 @@ * You should have received a copy of the GNU General Public License along with RetroArch. * If not, see . */ - #ifndef __RECORD_DRIVER_H #define __RECORD_DRIVER_H @@ -81,7 +80,7 @@ struct ffemu_audio_data size_t frames; }; -typedef struct ffemu_backend +typedef struct record_driver { void *(*init)(const struct ffemu_params *params); void (*free)(void *data); @@ -89,9 +88,19 @@ typedef struct ffemu_backend bool (*push_audio)(void *data, const struct ffemu_audio_data *audio_data); bool (*finalize)(void *data); const char *ident; -} ffemu_backend_t; +} record_driver_t; -extern const ffemu_backend_t ffemu_ffmpeg; +extern const record_driver_t ffemu_ffmpeg; +extern const record_driver_t ffemu_null; + +/** + * config_get_record_driver_options: + * + * Get an enumerated list of all record driver names, separated by '|'. + * + * Returns: string listing of all record driver names, separated by '|'. + **/ +const char* config_get_record_driver_options(void); /** * ffemu_find_backend: @@ -102,7 +111,25 @@ extern const ffemu_backend_t ffemu_ffmpeg; * Returns: recording driver handle if successful, otherwise * NULL. **/ -const ffemu_backend_t *ffemu_find_backend(const char *ident); +const record_driver_t *ffemu_find_backend(const char *ident); + +/** + * record_driver_find_handle: + * @idx : index of driver to get handle to. + * + * Returns: handle to record driver at index. Can be NULL + * if nothing found. + **/ +const void *record_driver_find_handle(int idx); + +/** + * record_driver_find_ident: + * @idx : index of driver to get handle to. + * + * Returns: Human-readable identifier of record driver at index. Can be NULL + * if nothing found. + **/ +const char *record_driver_find_ident(int idx); /** * gfx_ctx_init_first: @@ -114,7 +141,7 @@ const ffemu_backend_t *ffemu_find_backend(const char *ident); * * Returns: true (1) if successful, otherwise false (0). **/ -bool ffemu_init_first(const ffemu_backend_t **backend, void **data, +bool record_driver_init_first(const record_driver_t **backend, void **data, const struct ffemu_params *params); void recording_dump_frame(const void *data, unsigned width, diff --git a/settings.c b/settings.c index d8b6a9a0f3..bcf7594b27 100644 --- a/settings.c +++ b/settings.c @@ -3564,6 +3564,17 @@ static bool setting_append_list_driver_options( settings_data_list_current_add_flags(list, list_info, SD_FLAG_IS_DRIVER); #endif + CONFIG_STRING_OPTIONS( + settings->record.driver, + "record_driver", + "Record Driver", + config_get_default_record(), + config_get_record_driver_options(), + group_info.name, + subgroup_info.name, + NULL, + NULL); + settings_data_list_current_add_flags(list, list_info, SD_FLAG_IS_DRIVER); END_SUB_GROUP(list, list_info); END_GROUP(list, list_info);