diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 743c3b04..fd5b3fa5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -461,6 +461,7 @@ set(SRC_DRIVERS_SDL ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/ColorMenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GuiConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MoviePlay.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MovieRecord.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MovieOptions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/LuaControl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/CheatsConf.cpp diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index a0274c04..14cc489f 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -71,6 +71,7 @@ #include "Qt/GuiConf.h" #include "Qt/AviRecord.h" #include "Qt/MoviePlay.h" +#include "Qt/MovieRecord.h" #include "Qt/MovieOptions.h" #include "Qt/TimingConf.h" #include "Qt/FrameTimingStats.h" @@ -1636,19 +1637,11 @@ void consoleWin_t::createMainMenu(void) recMovAct->setIcon( QIcon(":icons/media-record.png") ); connect(recMovAct, SIGNAL(triggered()), this, SLOT(recordMovie(void)) ); + Hotkeys[ HK_RECORD_MOVIE_TO ].setAction( recMovAct ); + connect( Hotkeys[ HK_RECORD_MOVIE_TO ].getShortcut(), SIGNAL(activated()), this, SLOT(recordMovie(void)) ); + movieMenu->addAction(recMovAct); - // Movie -> Record As - recAsMovAct = new QAction(tr("Record &As"), this); - //recAsMovAct->setShortcut( QKeySequence(tr("Shift+F5"))); - recAsMovAct->setStatusTip(tr("Record Movie")); - connect(recAsMovAct, SIGNAL(triggered()), this, SLOT(recordMovieAs(void)) ); - - Hotkeys[ HK_RECORD_MOVIE_TO ].setAction( recAsMovAct ); - connect( Hotkeys[ HK_RECORD_MOVIE_TO ].getShortcut(), SIGNAL(activated()), this, SLOT(recordMovieAs(void)) ); - - movieMenu->addAction(recAsMovAct); - movieMenu->addSeparator(); // Movie -> Avi Recording @@ -3450,74 +3443,10 @@ void consoleWin_t::recordMovie(void) fceuWrapperLock(); if (fceuWrapperGameLoaded()) { - std::string name = FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0); - FCEUI_printf ("Recording movie to %s\n", name.c_str ()); - FCEUI_SaveMovie (name.c_str (), MOVIE_FLAG_NONE, L""); + MovieRecordDialog_t dialog(this); + dialog.exec(); } fceuWrapperUnLock(); - return; -} - -void consoleWin_t::recordMovieAs(void) -{ - int ret, useNativeFileDialogVal; - QString filename; - std::string last; - char dir[512]; - QFileDialog dialog(this, tr("Save FM2 Movie for Recording") ); - - dialog.setFileMode(QFileDialog::AnyFile); - - dialog.setNameFilter(tr("FM2 Movies (*.fm2) ;; All files (*)")); - - dialog.setViewMode(QFileDialog::List); - dialog.setFilter( QDir::AllEntries | QDir::AllDirs | QDir::Hidden ); - dialog.setLabelText( QFileDialog::Accept, tr("Save") ); - dialog.setDefaultSuffix( tr(".fm2") ); - - g_config->getOption ("SDL.LastOpenMovie", &last ); - - getDirFromFile( last.c_str(), dir ); - - dialog.setDirectory( tr(dir) ); - - // Check config option to use native file dialog or not - g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal); - - dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal); - - ret = dialog.exec(); - - if ( ret ) - { - QStringList fileList; - fileList = dialog.selectedFiles(); - - if ( fileList.size() > 0 ) - { - filename = fileList[0]; - } - } - - if ( filename.isNull() ) - { - return; - } - qDebug() << "selected file path : " << filename.toUtf8(); - - int pauseframe; - g_config->getOption ("SDL.PauseFrame", &pauseframe); - g_config->setOption ("SDL.PauseFrame", 0); - - FCEUI_printf ("Recording movie to %s\n", filename.toStdString().c_str() ); - - fceuWrapperLock(); - std::string s = GetUserText ("Author name"); - std::wstring author (s.begin (), s.end ()); - - FCEUI_SaveMovie ( filename.toStdString().c_str(), MOVIE_FLAG_NONE, author); - fceuWrapperUnLock(); - return; } @@ -4042,7 +3971,6 @@ void consoleWin_t::updatePeriodic(void) saveStateAct->setEnabled( FCEU_IsValidUI( FCEUI_SAVESTATE ) ); openMovAct->setEnabled( FCEU_IsValidUI( FCEUI_PLAYMOVIE ) ); recMovAct->setEnabled( FCEU_IsValidUI( FCEUI_RECORDMOVIE ) ); - recAsMovAct->setEnabled( FCEU_IsValidUI( FCEUI_RECORDMOVIE ) ); recAviAct->setEnabled( FCEU_IsValidUI( FCEUI_RECORDMOVIE ) && !FCEU_IsValidUI( FCEUI_STOPAVI ) ); recAsAviAct->setEnabled( FCEU_IsValidUI( FCEUI_RECORDMOVIE ) && !FCEU_IsValidUI( FCEUI_STOPAVI ) ); stopAviAct->setEnabled( FCEU_IsValidUI( FCEUI_STOPAVI ) ); diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index 0dc31509..7640fdd8 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -233,7 +233,6 @@ class consoleWin_t : public QMainWindow QAction *playMovBeginAct; QAction *stopMovAct; QAction *recMovAct; - QAction *recAsMovAct; QAction *region[3]; QAction *ramInit[4]; QAction *recAviAct; @@ -294,6 +293,7 @@ class consoleWin_t : public QMainWindow void openGamePadConfWin(void); void toggleFullscreen(void); void toggleMenuVis(void); + void recordMovie(void); private slots: void closeApp(void); void openROMFile(void); @@ -371,8 +371,6 @@ class consoleWin_t : public QMainWindow void openRamSearch(void); void openMovie(void); void stopMovie(void); - void recordMovie(void); - void recordMovieAs(void); void playMovieFromBeginning(void); void setCustomAutoFire(void); void incrSoundVolume(void); diff --git a/src/drivers/Qt/MovieRecord.cpp b/src/drivers/Qt/MovieRecord.cpp new file mode 100644 index 00000000..0841b78e --- /dev/null +++ b/src/drivers/Qt/MovieRecord.cpp @@ -0,0 +1,369 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 mjbudd77 + * + * This program 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 program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +// MovieRecord.cpp +// +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../fceu.h" +#include "../../movie.h" + +#include "Qt/main.h" +#include "Qt/dface.h" +#include "Qt/input.h" +#include "Qt/config.h" +#include "Qt/keyscan.h" +#include "Qt/fceuWrapper.h" +#include "Qt/ConsoleUtilities.h" +#include "Qt/MovieRecord.h" + +//---------------------------------------------------------------------------- +MovieRecordDialog_t::MovieRecordDialog_t(QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *mainLayout; + QHBoxLayout *hbox; + QGridLayout *grid; + QSettings settings; + std::string name; + + setWindowTitle( tr("Record Input Movie") ); + + mainLayout = new QVBoxLayout(); + grid = new QGridLayout(); + hbox = new QHBoxLayout(); + + setLayout( mainLayout ); + + mainLayout->addLayout( grid ); + mainLayout->addLayout( hbox ); + + dirEdit = new QLineEdit(); + fileEdit = new QLineEdit(); + authorEdit = new QLineEdit(); + fileBrowse = new QPushButton( tr("...") ); + stateSel = new QComboBox(); + okButton = new QPushButton( tr("OK") ); + cancelButton = new QPushButton( tr("Cancel") ); + + okButton->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton)); + cancelButton->setIcon(style()->standardIcon(QStyle::SP_DialogCancelButton)); + fileBrowse->setIcon(style()->standardIcon(QStyle::SP_FileDialogStart) ); + + stateSel->addItem( tr("Start") , 0 ); + stateSel->addItem( tr("Now") , 1 ); + stateSel->addItem( tr("Save RAM") , 2 ); + stateSel->addItem( tr("Browse..."), 3 ); + + grid->addWidget( new QLabel( tr("Path:") ), 0, 0 ); + grid->addWidget( dirEdit , 0, 1 ); + + grid->addWidget( new QLabel( tr("File:") ), 1, 0 ); + grid->addWidget( fileEdit , 1, 1 ); + grid->addWidget( fileBrowse, 1, 2 ); + + grid->addWidget( new QLabel( tr("Record:") ), 2, 0 ); + grid->addWidget( stateSel , 2, 1 ); + + grid->addWidget( new QLabel( tr("Author:") ), 3, 0 ); + grid->addWidget( authorEdit , 3, 1 ); + + hbox->addWidget( cancelButton, 1 ); + hbox->addStretch(10); + hbox->addWidget( okButton, 1 ); + + dirEdit->setReadOnly(true); + + setFilePath( FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0) ); + + connect( fileBrowse, SIGNAL(clicked(void)), this, SLOT(browseFiles(void)) ); + connect( okButton, SIGNAL(clicked(void)), this, SLOT(recordMovie(void)) ); + connect( cancelButton, SIGNAL(clicked(void)), this, SLOT(reject(void)) ); + + connect( stateSel, SIGNAL(activated(int)), this, SLOT(stateSelChanged(int)) ); + + okButton->setDefault(true); + + restoreGeometry(settings.value("movieRecordWindow/geometry").toByteArray()); +} +//---------------------------------------------------------------------------- +MovieRecordDialog_t::~MovieRecordDialog_t(void) +{ + QSettings settings; + settings.setValue("movieRecordWindow/geometry", saveGeometry()); + //printf("Destroy Movie Play Window\n"); +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::closeEvent(QCloseEvent *event) +{ + QSettings settings; + settings.setValue("movieRecordWindow/geometry", saveGeometry()); + done(0); + deleteLater(); + event->accept(); +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::closeWindow(void) +{ + QSettings settings; + settings.setValue("movieRecordWindow/geometry", saveGeometry()); + done(0); + deleteLater(); +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::setFilePath( const char *s ) +{ + setFilePath( tr(s) ); +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::setFilePath( std::string s ) +{ + setFilePath( QString::fromStdString(s) ); +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::setFilePath( QString s ) +{ + QFileInfo fi(s); + + dirEdit->setText( fi.absolutePath() ); + fileEdit->setText( fi.fileName() ); + + filepath = s.toStdString(); +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::stateSelChanged( int idx ) +{ + //printf("State:%i\n", idx); + + if ( idx >= 3 ) + { + setLoadState(); + okButton->setEnabled( ic_file.size() > 0 ); + } + else + { + okButton->setEnabled( true ); + } +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::setLoadState(void) +{ + int ret, useNativeFileDialogVal; + QString filename; + std::string last; + char dir[512]; + const char *base; + QFileDialog dialog(this, tr("Load State From File") ); + QList urls; + QDir d; + + base = FCEUI_GetBaseDirectory(); + + urls << QUrl::fromLocalFile( QDir::rootPath() ); + urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first()); + urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DownloadLocation).first()); + + if ( base ) + { + urls << QUrl::fromLocalFile( QDir( base ).absolutePath() ); + + d.setPath( QString(base) + "/fcs"); + + if ( d.exists() ) + { + urls << QUrl::fromLocalFile( d.absolutePath() ); + } + + d.setPath( QString(base) + "/sav"); + + if ( d.exists() ) + { + urls << QUrl::fromLocalFile( d.absolutePath() ); + } + } + + + dialog.setFileMode(QFileDialog::ExistingFile); + + dialog.setNameFilter(tr("FCS & SAV Files (*.sav *.SAV *.fc? *.FC?) ;; All files (*)")); + + dialog.setViewMode(QFileDialog::List); + dialog.setFilter( QDir::AllEntries | QDir::AllDirs | QDir::Hidden ); + dialog.setLabelText( QFileDialog::Accept, tr("Select") ); + + g_config->getOption ("SDL.LastLoadStateFrom", &last ); + + getDirFromFile( last.c_str(), dir ); + + dialog.setDirectory( tr(dir) ); + + // Check config option to use native file dialog or not + g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal); + + dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal); + dialog.setSidebarUrls(urls); + + ret = dialog.exec(); + + if ( ret ) + { + QStringList fileList; + fileList = dialog.selectedFiles(); + + if ( fileList.size() > 0 ) + { + filename = fileList[0]; + } + } + + if ( filename.isNull() ) + { + return; + } + qDebug() << "selected file path : " << filename.toUtf8(); + + g_config->setOption ("SDL.LastLoadStateFrom", filename.toStdString().c_str() ); + + ic_file = filename.toStdString(); +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::recordMovie(void) +{ + bool startRecording = true; + + if (fceuWrapperGameLoaded()) + { + QString qs; + int recordFrom = stateSel->currentIndex(); + EMOVIE_FLAG flags = MOVIE_FLAG_NONE; + if (recordFrom == 0) flags = MOVIE_FLAG_FROM_POWERON; + if (recordFrom == 2) flags = MOVIE_FLAG_FROM_SAVERAM; + + if ( recordFrom >= 3 ) + { + FCEUI_LoadState(ic_file.c_str()); + { + extern int loadStateFailed; + + if (loadStateFailed) + { + char str [1024]; + sprintf(str, "Failed to load save state \"%s\".\nRecording from current state instead...", ic_file.c_str()); + FCEUD_PrintError(str); + } + } + } + qs = QString::fromStdString(filepath); + + if ( QFile::exists(qs) ) + { + int ret; + + ret = QMessageBox::warning( this, tr("Overwrite Warning"), + tr("Pre-existing movie file Will be overwritten.\nReplace file?"), QMessageBox::Yes | QMessageBox::No ); + + if ( ret == QMessageBox::No ) + { + startRecording = false; + } + + } + + if ( startRecording ) + { + std::string s = authorEdit->text().toStdString(); + std::wstring author (s.begin (), s.end ()); + FCEUI_printf("Recording movie to %s\n", filepath.c_str ()); + FCEUI_SaveMovie (filepath.c_str(), flags, author); + + done(0); + deleteLater(); + } + } +} +//---------------------------------------------------------------------------- +void MovieRecordDialog_t::browseFiles(void) +{ + int ret, useNativeFileDialogVal; + QString filename; + std::string last; + char dir[512]; + QFileDialog dialog(this, tr("Save FM2 Movie for Recording") ); + + dialog.setFileMode(QFileDialog::AnyFile); + + dialog.setNameFilter(tr("FM2 Movies (*.fm2) ;; All files (*)")); + + dialog.setViewMode(QFileDialog::List); + dialog.setFilter( QDir::AllEntries | QDir::AllDirs | QDir::Hidden ); + dialog.setLabelText( QFileDialog::Accept, tr("Save To") ); + dialog.setDefaultSuffix( tr(".fm2") ); + + g_config->getOption ("SDL.LastOpenMovie", &last ); + + getDirFromFile( last.c_str(), dir ); + + dialog.setDirectory( tr(dir) ); + + // Check config option to use native file dialog or not + g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal); + + dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal); + + ret = dialog.exec(); + + if ( ret ) + { + QStringList fileList; + fileList = dialog.selectedFiles(); + + if ( fileList.size() > 0 ) + { + filename = fileList[0]; + } + } + + if ( filename.isNull() ) + { + return; + } + qDebug() << "selected file path : " << filename.toUtf8(); + + int pauseframe; + g_config->getOption ("SDL.PauseFrame", &pauseframe); + g_config->setOption ("SDL.PauseFrame", 0); + + FCEUI_printf ("Recording movie to %s\n", filename.toStdString().c_str() ); + setFilePath( filename ); + + return; +} +//---------------------------------------------------------------------------- diff --git a/src/drivers/Qt/MovieRecord.h b/src/drivers/Qt/MovieRecord.h new file mode 100644 index 00000000..c820a095 --- /dev/null +++ b/src/drivers/Qt/MovieRecord.h @@ -0,0 +1,54 @@ +// MovieRecord.h +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Qt/main.h" +#include "Qt/ConsoleUtilities.h" + +class MovieRecordDialog_t : public QDialog +{ + Q_OBJECT + +public: + MovieRecordDialog_t(QWidget *parent = 0); + ~MovieRecordDialog_t(void); + +protected: + void closeEvent(QCloseEvent *event); + + QLineEdit *dirEdit; + QLineEdit *fileEdit; + QLineEdit *authorEdit; + QPushButton *fileBrowse; + QPushButton *okButton; + QPushButton *cancelButton; + QComboBox *stateSel; + std::string filepath; + std::string ic_file; + +private: + void setFilePath( QString s ); + void setFilePath( std::string s ); + void setFilePath( const char *s ); + void setLoadState(void); + +public slots: + void closeWindow(void); +private slots: + void browseFiles(void); + void recordMovie(void); + void stateSelChanged(int idx); +}; diff --git a/src/drivers/Qt/input.cpp b/src/drivers/Qt/input.cpp index 59c89f78..33cd0cd4 100644 --- a/src/drivers/Qt/input.cpp +++ b/src/drivers/Qt/input.cpp @@ -19,6 +19,7 @@ */ #include +#include #include #include "Qt/main.h" @@ -644,25 +645,27 @@ static std::string GetFilename(const char *title, int mode, const char *filter) return fname; } -/** - * This function opens a text entry dialog and returns the user's input - */ -std::string GetUserText(const char *title) -{ - return ""; -} - /** * Lets the user start a new .fm2 movie file **/ void FCEUD_MovieRecordTo(void) { - std::string fname = GetFilename("Save FM2 movie for recording", 2, "FM2 movies|*.fm2"); - if (!fname.size()) - return; // no filename selected, quit the whole thing - std::wstring author = mbstowcs(GetUserText("Author Name")); // the author can be empty, so no need to check here + //bool ok = false; + //std::string fname = GetFilename("Save FM2 movie for recording", 2, "FM2 movies|*.fm2"); + //if (!fname.size()) + //{ + // return; // no filename selected, quit the whole thing + //} + //std::string s = QInputDialog::getText( consoleWindow, QObject::tr("Movie Recording"), + // QObject::tr("Enter Author Name"), QLineEdit::Normal, QObject::tr(""), &ok ).toStdString(); - FCEUI_SaveMovie(fname.c_str(), MOVIE_FLAG_FROM_POWERON, author); + //std::wstring author (s.begin (), s.end ()); + + //FCEUI_SaveMovie(fname.c_str(), MOVIE_FLAG_FROM_POWERON, author); + if ( consoleWindow ) + { + consoleWindow->recordMovie(); + } } /** diff --git a/src/drivers/Qt/input.h b/src/drivers/Qt/input.h index 8c75c5f9..940b0d5f 100644 --- a/src/drivers/Qt/input.h +++ b/src/drivers/Qt/input.h @@ -140,7 +140,6 @@ void FCEUD_UpdateInput(void); void UpdateInput(Config *config); -std::string GetUserText(const char* title); const char* ButtonName(const ButtConfig* bc); int getInputSelection( int port, int *cur, int *usr );