Linux (gtk): Add preliminary AV recording with x264 and flac.
This commit is contained in:
parent
a15e6cee10
commit
6f91e947c3
|
@ -10,6 +10,10 @@ pixmap_DATA = DeSmuME.xpm
|
|||
EXTRA_DIST = DeSmuME.xpm desmume.desktop
|
||||
bin_PROGRAMS = desmume
|
||||
desmume_SOURCES = \
|
||||
avout.h \
|
||||
avout_pipe_base.cpp avout_pipe_base.h \
|
||||
avout_x264.cpp avout_x264.h \
|
||||
avout_flac.cpp avout_flac.h \
|
||||
desmume.h desmume.cpp \
|
||||
dTool.h dToolsList.cpp \
|
||||
tools/ioregsView.cpp tools/ioregsView.h \
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (C) 2014 DeSmuME team
|
||||
|
||||
This file 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AVOUT_H_
|
||||
#define _AVOUT_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
class AVOut {
|
||||
public:
|
||||
virtual bool begin(const char* fname) { return false; }
|
||||
virtual void end() {}
|
||||
virtual bool isRecording() { return false; }
|
||||
virtual void updateAudio(void* soundData, int soundLen) {}
|
||||
virtual void updateVideo(const u16* buffer) {}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright (C) 2014 DeSmuME team
|
||||
|
||||
This file 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "avout_flac.h"
|
||||
|
||||
AVOutFlac::AVOutFlac() {
|
||||
const char* const args[] = {
|
||||
"flac",
|
||||
"-f",
|
||||
"-o", this->filename,
|
||||
"--endian=little",
|
||||
"--channels=2",
|
||||
"--bps=16",
|
||||
"--sample-rate=44100",
|
||||
"--sign=signed",
|
||||
"--force-raw-format",
|
||||
"-",
|
||||
NULL
|
||||
};
|
||||
memcpy(this->args, args, sizeof(args));
|
||||
}
|
||||
|
||||
const char* const* AVOutFlac::getArgv(const char* fname) {
|
||||
if (strlen(fname) >= sizeof(this->filename)) {
|
||||
return NULL;
|
||||
}
|
||||
strncpy(this->filename, fname, sizeof(this->filename));
|
||||
return this->args;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
Copyright (C) 2014 DeSmuME team
|
||||
|
||||
This file 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AVOUT_FLAC_H_
|
||||
#define _AVOUT_FLAC_H_
|
||||
|
||||
#include "avout_pipe_base.h"
|
||||
|
||||
class AVOutFlac : public AVOutPipeBase {
|
||||
public:
|
||||
AVOutFlac();
|
||||
protected:
|
||||
Type type() { return TYPE_AUDIO; }
|
||||
const char* const* getArgv(const char* fname);
|
||||
private:
|
||||
char filename[1024];
|
||||
const char* args[12];
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Copyright (C) 2014 DeSmuME team
|
||||
|
||||
This file 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <cerrno>
|
||||
|
||||
#include "types.h"
|
||||
#include "SPU.h"
|
||||
|
||||
#include "avout_pipe_base.h"
|
||||
|
||||
static inline int writeAll(int fd, const void* buf, size_t count) {
|
||||
ssize_t written = 0, writtenTotal = 0;
|
||||
do {
|
||||
written = write(fd, ((u8*)buf) + writtenTotal, count - writtenTotal);
|
||||
} while (written >= 0 && (writtenTotal += written) < count);
|
||||
return written;
|
||||
}
|
||||
|
||||
bool AVOutPipeBase::begin(const char* fname) {
|
||||
if (this->recording) {
|
||||
return false;
|
||||
}
|
||||
const char* const* args = this->getArgv(fname);
|
||||
if (args == NULL) {
|
||||
return false;
|
||||
}
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd) < 0) {
|
||||
fprintf(stderr, "Fail to open pipe\n");
|
||||
return false;
|
||||
}
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
close(pipefd[1]);
|
||||
dup2(pipefd[0], STDIN_FILENO);
|
||||
execvp(args[0], (char* const*)args);
|
||||
fprintf(stderr, "Fail to start %s: %d %s\n", args[0], errno, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
close(pipefd[0]);
|
||||
this->pipe_fd = pipefd[1];
|
||||
this->recording = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVOutPipeBase::end() {
|
||||
if (this->recording) {
|
||||
close(this->pipe_fd);
|
||||
this->recording = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool AVOutPipeBase::isRecording() {
|
||||
return this->recording;
|
||||
}
|
||||
|
||||
void AVOutPipeBase::updateAudio(void* soundData, int soundLen) {
|
||||
if(!this->recording || this->type() != TYPE_AUDIO) {
|
||||
return;
|
||||
}
|
||||
if (writeAll(this->pipe_fd, soundData, soundLen * 2 * 2) == -1) {
|
||||
fprintf(stderr, "Error on writing audio: %d %s\n", errno, strerror(errno));
|
||||
this->end();
|
||||
}
|
||||
}
|
||||
|
||||
void AVOutPipeBase::updateVideo(const u16* buffer) {
|
||||
if(!this->recording || this->type() != TYPE_VIDEO) {
|
||||
return;
|
||||
}
|
||||
u8 rgb[256 * 384 * 3];
|
||||
u8* cur = rgb;
|
||||
for (int i = 0; i < 256 * 384; i++) {
|
||||
u16 gpu_pixel = buffer[i];
|
||||
*cur = ((gpu_pixel >> 0) & 0x1f) << 3;
|
||||
cur++;
|
||||
*cur = ((gpu_pixel >> 5) & 0x1f) << 3;
|
||||
cur++;
|
||||
*cur = ((gpu_pixel >> 10) & 0x1f) << 3;
|
||||
cur++;
|
||||
}
|
||||
if (write(this->pipe_fd, rgb, 256 * 384 * 3) == -1) {
|
||||
fprintf(stderr, "Error on writing video: %d %s\n", errno, strerror(errno));
|
||||
this->end();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright (C) 2014 DeSmuME team
|
||||
|
||||
This file 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AVOUT_PIPE_BASE_H_
|
||||
#define _AVOUT_PIPE_BASE_H_
|
||||
|
||||
#include "avout.h"
|
||||
|
||||
class AVOutPipeBase : public AVOut {
|
||||
public:
|
||||
bool begin(const char* fname);
|
||||
void end();
|
||||
bool isRecording();
|
||||
void updateAudio(void* soundData, int soundLen);
|
||||
void updateVideo(const u16* buffer);
|
||||
protected:
|
||||
enum Type { TYPE_AUDIO, TYPE_VIDEO };
|
||||
virtual Type type() = 0;
|
||||
virtual const char* const* getArgv(const char* fname) = 0;
|
||||
private:
|
||||
bool recording;
|
||||
int pipe_fd;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright (C) 2014 DeSmuME team
|
||||
|
||||
This file 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "avout_x264.h"
|
||||
|
||||
AVOutX264::AVOutX264() {
|
||||
const char* const args[] = {
|
||||
"x264",
|
||||
"--qp", "0",
|
||||
"--demuxer", "raw",
|
||||
"--input-csp", "rgb",
|
||||
"--input-depth", "8",
|
||||
"--input-res", "256x384",
|
||||
"--fps", "60",
|
||||
"--output-csp", "i444",
|
||||
"-o", this->filename,
|
||||
"-",
|
||||
NULL
|
||||
};
|
||||
memcpy(this->args, args, sizeof(args));
|
||||
}
|
||||
|
||||
const char* const* AVOutX264::getArgv(const char* fname) {
|
||||
if (strlen(fname) >= sizeof(this->filename)) {
|
||||
return NULL;
|
||||
}
|
||||
strncpy(this->filename, fname, sizeof(this->filename));
|
||||
return this->args;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
Copyright (C) 2014 DeSmuME team
|
||||
|
||||
This file 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 Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AVOUT_X264_H_
|
||||
#define _AVOUT_X264_H_
|
||||
|
||||
#include "avout_pipe_base.h"
|
||||
|
||||
class AVOutX264 : public AVOutPipeBase {
|
||||
public:
|
||||
AVOutX264();
|
||||
protected:
|
||||
Type type() { return TYPE_VIDEO; }
|
||||
const char* const* getArgv(const char* fname);
|
||||
private:
|
||||
char filename[1024];
|
||||
const char* args[19];
|
||||
};
|
||||
|
||||
#endif
|
|
@ -51,6 +51,9 @@
|
|||
#include "cheatsGTK.h"
|
||||
#include "GPU_osd.h"
|
||||
|
||||
#include "avout_x264.h"
|
||||
#include "avout_flac.h"
|
||||
|
||||
#include "commandline.h"
|
||||
|
||||
#include "slot2.h"
|
||||
|
@ -106,6 +109,12 @@ enum {
|
|||
|
||||
gboolean EmuLoop(gpointer data);
|
||||
|
||||
static AVOutX264 avout_x264;
|
||||
static AVOutFlac avout_flac;
|
||||
static void RecordAV_x264();
|
||||
static void RecordAV_flac();
|
||||
static void RecordAV_stop();
|
||||
|
||||
static void DoQuit();
|
||||
static void RecordMovieDialog();
|
||||
static void PlayMovieDialog();
|
||||
|
@ -186,6 +195,12 @@ static const char *ui_description =
|
|||
" <menuitem action='recordmovie'/>"
|
||||
" <menuitem action='playmovie'/>"
|
||||
" <menuitem action='stopmovie'/>"
|
||||
" <separator/>"
|
||||
" <menu action='RecordAVMenu'>"
|
||||
" <menuitem action='record_x264'/>"
|
||||
" <menuitem action='record_flac'/>"
|
||||
" <menuitem action='record_stop'/>"
|
||||
" </menu>"
|
||||
" <menuitem action='printscreen'/>"
|
||||
" <separator/>"
|
||||
" <menuitem action='quit'/>"
|
||||
|
@ -341,6 +356,10 @@ static const GtkActionEntry action_entries[] = {
|
|||
{ "recordmovie", NULL, "Record movie _to ...", NULL, NULL, RecordMovieDialog },
|
||||
{ "playmovie", NULL, "Play movie _from ...", NULL, NULL, PlayMovieDialog },
|
||||
{ "stopmovie", NULL, "Stop movie", NULL, NULL, StopMovie },
|
||||
{ "RecordAVMenu", NULL, "Record _video/audio" },
|
||||
{ "record_x264", "gtk-media-record", "Record lossless H._264 (video only)...", NULL, NULL, RecordAV_x264 },
|
||||
{ "record_flac", "gtk-media-record", "Record _flac (audio only)...", NULL, NULL, RecordAV_flac },
|
||||
{ "record_stop", "gtk-media-stop", "_Stop recording", NULL, NULL, RecordAV_stop },
|
||||
{ "SavestateMenu", NULL, "_Save state" },
|
||||
{ "LoadstateMenu", NULL, "_Load state" },
|
||||
#ifdef DESMUME_GTK_FIRMWARE_BROKEN
|
||||
|
@ -1063,6 +1082,138 @@ static void SaveStateDialog()
|
|||
gtk_widget_destroy(pFileSelection);
|
||||
}
|
||||
|
||||
static void RecordAV_x264()
|
||||
{
|
||||
GtkFileFilter *pFilter_mkv, *pFilter_mp4, *pFilter_any;
|
||||
GtkWidget *pFileSelection;
|
||||
GtkWidget *pParent;
|
||||
gchar *sPath;
|
||||
|
||||
if (desmume_running())
|
||||
Pause();
|
||||
|
||||
pParent = GTK_WIDGET(pWindow);
|
||||
|
||||
pFilter_mkv = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(pFilter_mkv, "*.mkv");
|
||||
gtk_file_filter_set_name(pFilter_mkv, "Matroska (.mkv)");
|
||||
|
||||
pFilter_mp4 = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(pFilter_mp4, "*.mp4");
|
||||
gtk_file_filter_set_name(pFilter_mp4, "MP4 (.mp4)");
|
||||
|
||||
pFilter_any = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(pFilter_any, "*");
|
||||
gtk_file_filter_set_name(pFilter_any, "All files");
|
||||
|
||||
/* Creating the selection window */
|
||||
pFileSelection = gtk_file_chooser_dialog_new("Save video...",
|
||||
GTK_WINDOW(pParent),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_OK,
|
||||
NULL);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (pFileSelection), TRUE);
|
||||
|
||||
/* Only the dialog window is accepting events: */
|
||||
gtk_window_set_modal(GTK_WINDOW(pFileSelection), TRUE);
|
||||
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_mkv);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_mp4);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_any);
|
||||
|
||||
/* Showing the window */
|
||||
switch(gtk_dialog_run(GTK_DIALOG(pFileSelection))) {
|
||||
case GTK_RESPONSE_OK:
|
||||
sPath = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSelection));
|
||||
|
||||
if(avout_x264.begin(sPath)) {
|
||||
gtk_action_set_sensitive(gtk_action_group_get_action(action_group, "record_x264"), FALSE);
|
||||
} else {
|
||||
GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection),
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
"Unable to record video to:\n%s", sPath);
|
||||
gtk_dialog_run(GTK_DIALOG(pDialog));
|
||||
gtk_widget_destroy(pDialog);
|
||||
}
|
||||
|
||||
g_free(sPath);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gtk_widget_destroy(pFileSelection);
|
||||
}
|
||||
|
||||
static void RecordAV_flac()
|
||||
{
|
||||
GtkFileFilter *pFilter_flac, *pFilter_any;
|
||||
GtkWidget *pFileSelection;
|
||||
GtkWidget *pParent;
|
||||
gchar *sPath;
|
||||
|
||||
if (desmume_running())
|
||||
Pause();
|
||||
|
||||
pParent = GTK_WIDGET(pWindow);
|
||||
|
||||
pFilter_flac = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(pFilter_flac, "*.flac");
|
||||
gtk_file_filter_set_name(pFilter_flac, "FLAC file (.flac)");
|
||||
|
||||
pFilter_any = gtk_file_filter_new();
|
||||
gtk_file_filter_add_pattern(pFilter_any, "*");
|
||||
gtk_file_filter_set_name(pFilter_any, "All files");
|
||||
|
||||
/* Creating the selection window */
|
||||
pFileSelection = gtk_file_chooser_dialog_new("Save audio...",
|
||||
GTK_WINDOW(pParent),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_SAVE, GTK_RESPONSE_OK,
|
||||
NULL);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (pFileSelection), TRUE);
|
||||
|
||||
/* Only the dialog window is accepting events: */
|
||||
gtk_window_set_modal(GTK_WINDOW(pFileSelection), TRUE);
|
||||
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_flac);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(pFileSelection), pFilter_any);
|
||||
|
||||
/* Showing the window */
|
||||
switch(gtk_dialog_run(GTK_DIALOG(pFileSelection))) {
|
||||
case GTK_RESPONSE_OK:
|
||||
sPath = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSelection));
|
||||
|
||||
if(avout_flac.begin(sPath)) {
|
||||
gtk_action_set_sensitive(gtk_action_group_get_action(action_group, "record_flac"), FALSE);
|
||||
} else {
|
||||
GtkWidget *pDialog = gtk_message_dialog_new(GTK_WINDOW(pFileSelection),
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_OK,
|
||||
"Unable to record audio to:\n%s", sPath);
|
||||
gtk_dialog_run(GTK_DIALOG(pDialog));
|
||||
gtk_widget_destroy(pDialog);
|
||||
}
|
||||
|
||||
g_free(sPath);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gtk_widget_destroy(pFileSelection);
|
||||
}
|
||||
|
||||
static void RecordAV_stop() {
|
||||
avout_x264.end();
|
||||
avout_flac.end();
|
||||
gtk_action_set_sensitive(gtk_action_group_get_action(action_group, "record_x264"), TRUE);
|
||||
gtk_action_set_sensitive(gtk_action_group_get_action(action_group, "record_flac"), TRUE);
|
||||
}
|
||||
|
||||
static void OpenNdsDialog()
|
||||
{
|
||||
GtkFileFilter *pFilter_nds, *pFilter_dsgba, *pFilter_any;
|
||||
|
@ -1181,9 +1332,13 @@ static void OpenRecent(GtkRecentChooser *chooser, gpointer user_data)
|
|||
|
||||
static void Reset()
|
||||
{
|
||||
bool shouldBeRunning = desmume_running();
|
||||
Pause();
|
||||
NDS_Reset();
|
||||
if (shouldBeRunning) {
|
||||
Launch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////// DRAWING SCREEN //////////////////////////////////
|
||||
|
@ -2035,6 +2190,18 @@ public:
|
|||
while (gtk_events_pending())
|
||||
gtk_main_iteration();
|
||||
}
|
||||
|
||||
// HUD uses this to show pause state
|
||||
virtual bool EMU_IsEmulationPaused() { return !desmume_running(); }
|
||||
|
||||
virtual bool AVI_IsRecording()
|
||||
{
|
||||
return avout_x264.isRecording() || avout_flac.isRecording();
|
||||
}
|
||||
|
||||
virtual void AVI_SoundUpdate(void* soundData, int soundLen) {
|
||||
avout_flac.updateAudio(soundData, soundLen);
|
||||
}
|
||||
};
|
||||
|
||||
static void DoQuit()
|
||||
|
@ -2138,6 +2305,7 @@ gboolean EmuLoop(gpointer data)
|
|||
_updateDTools();
|
||||
gtk_widget_queue_draw( pDrawingArea );
|
||||
osd->clear();
|
||||
avout_x264.updateVideo((u16*)GPU_screen);
|
||||
|
||||
if (gtk_fps_limiter_disabled || keys_latch & KEYMASK_(KEY_BOOST - 1)) {
|
||||
if (autoframeskip) {
|
||||
|
@ -2747,6 +2915,9 @@ common_gtk_main( class configured_features *my_config)
|
|||
/* Main loop */
|
||||
gtk_main();
|
||||
|
||||
avout_x264.end();
|
||||
avout_flac.end();
|
||||
|
||||
desmume_free();
|
||||
|
||||
#if defined(HAVE_LIBOSMESA)
|
||||
|
|
Loading…
Reference in New Issue