Make video and audio providers throw typed exceptions.
Don't display error messages and try other providers when the user cancels loading a file. Remove files from the MRU lists if they can't be found. Closes #717. Originally committed to SVN as r4717.
This commit is contained in:
parent
71fb04cd29
commit
c10e9e3a5b
65 changed files with 574 additions and 1279 deletions
|
@ -131,16 +131,13 @@ namespace Endian {
|
|||
|
||||
|
||||
#ifndef HAVE_DYNAMIC_ENDIAN
|
||||
|
||||
|
||||
// Regular, fast, templatized conditional reversing
|
||||
|
||||
template <class T>
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param val
|
||||
/// @return
|
||||
///
|
||||
template <class T>
|
||||
inline T LittleToMachine(T val)
|
||||
{
|
||||
#ifdef HAVE_BIG_ENDIAN
|
||||
|
@ -152,12 +149,11 @@ namespace Endian {
|
|||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param val
|
||||
/// @return
|
||||
///
|
||||
template <class T>
|
||||
inline T BigToMachine(T val)
|
||||
{
|
||||
#ifdef HAVE_LITTLE_ENDIAN
|
||||
|
@ -169,12 +165,11 @@ namespace Endian {
|
|||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param val
|
||||
/// @return
|
||||
///
|
||||
template <class T>
|
||||
inline T MachineToLittle(T val)
|
||||
{
|
||||
#ifdef HAVE_BIG_ENDIAN
|
||||
|
@ -186,12 +181,11 @@ namespace Endian {
|
|||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param val
|
||||
/// @return
|
||||
///
|
||||
template <class T>
|
||||
inline T MachineToBig(T val)
|
||||
{
|
||||
#ifdef HAVE_LITTLE_ENDIAN
|
||||
|
@ -203,10 +197,8 @@ namespace Endian {
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
#else // HAVE_DYNAMIC_ENDIAN
|
||||
|
||||
|
||||
// Dynamic endianness handling
|
||||
|
||||
// Exploit that bit-shifting operations always can put bytes into
|
||||
|
@ -216,13 +208,11 @@ namespace Endian {
|
|||
// the endianness of the machine we are on, but it's the same
|
||||
// code for any platform!
|
||||
|
||||
|
||||
// Unions to pack together ints and get their physical bytes
|
||||
|
||||
|
||||
/// DOCME
|
||||
union bytes16 {
|
||||
|
||||
/// DOCME
|
||||
uint8_t byte[2];
|
||||
|
||||
|
@ -232,7 +222,6 @@ namespace Endian {
|
|||
|
||||
/// DOCME
|
||||
union bytes32 {
|
||||
|
||||
/// DOCME
|
||||
uint8_t byte[4];
|
||||
|
||||
|
@ -242,7 +231,6 @@ namespace Endian {
|
|||
|
||||
/// DOCME
|
||||
union bytes64 {
|
||||
|
||||
/// DOCME
|
||||
uint8_t byte[8];
|
||||
|
||||
|
@ -250,7 +238,6 @@ namespace Endian {
|
|||
uint64_t word;
|
||||
};
|
||||
|
||||
|
||||
// 16 bit words
|
||||
|
||||
|
||||
|
@ -456,8 +443,5 @@ namespace Endian {
|
|||
uint64_t(pack.byte[0]);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,5 @@
|
|||
// So unless we protect it by this, it gets included twice during production of precompiled
|
||||
// headers, which can cause problems with local includes.
|
||||
#ifndef AGI_PRE
|
||||
#include "config.h"
|
||||
|
||||
#include "agi_pre.h"
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#ifndef AGI_PRE_H
|
||||
|
||||
/// @brief Inclusion guard.
|
||||
/// @todo Why is this even nessicary? GCC seems to include agi_pre.h twice for no reason.
|
||||
/// @todo Why is this even necessary? GCC seems to include agi_pre.h twice for no reason.
|
||||
#define AGI_PRE_H
|
||||
|
||||
// C++ only
|
||||
|
|
|
@ -34,12 +34,8 @@
|
|||
/// @ingroup export
|
||||
///
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#ifndef AGI_PRE
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
@ -48,21 +44,14 @@
|
|||
#include <wx/window.h>
|
||||
#endif
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class AssFile;
|
||||
class AssExportFilter;
|
||||
class DialogExport;
|
||||
class AssExporter;
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
typedef std::list<AssExportFilter*> FilterList;
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class AssExportFilterChain
|
||||
/// @brief DOCME
|
||||
|
@ -80,7 +69,6 @@ private:
|
|||
/// DOCME
|
||||
FilterList Unprepared;
|
||||
|
||||
|
||||
/// DOCME
|
||||
static std::auto_ptr<AssExportFilterChain> instance;
|
||||
static FilterList *GetFilterList();
|
||||
|
@ -90,8 +78,6 @@ public:
|
|||
static void PrepareFilters();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class AssExportFilter
|
||||
/// @brief DOCME
|
||||
|
@ -139,4 +125,3 @@ public:
|
|||
virtual void LoadSettings(bool IsDefault); // Config dialog is done - extract data now.
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -36,16 +36,11 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
#include "ass_export_filter.h"
|
||||
#include "ass_exporter.h"
|
||||
#include "ass_file.h"
|
||||
#include "frame_main.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param subs
|
||||
///
|
||||
|
@ -54,15 +49,11 @@ AssExporter::AssExporter (AssFile *subs) {
|
|||
IsDefault = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
AssExporter::~AssExporter () {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Draw control settings
|
||||
/// @param parent
|
||||
/// @param AddTo
|
||||
|
@ -90,8 +81,6 @@ void AssExporter::DrawSettings(wxWindow *parent,wxSizer *AddTo) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Add filter to chain
|
||||
/// @param name
|
||||
///
|
||||
|
@ -113,8 +102,6 @@ void AssExporter::AddFilter(wxString name) {
|
|||
Filters.push_back(filter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Adds all autoexporting filters to chain
|
||||
///
|
||||
void AssExporter::AddAutoFilters() {
|
||||
|
@ -127,8 +114,6 @@ void AssExporter::AddAutoFilters() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get name of all filters
|
||||
/// @return
|
||||
///
|
||||
|
@ -142,8 +127,6 @@ wxArrayString AssExporter::GetAllFilterNames() {
|
|||
return names;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Transform for export
|
||||
/// @param export_dialog
|
||||
/// @return
|
||||
|
@ -162,8 +145,6 @@ AssFile *AssExporter::ExportTransform(wxWindow *export_dialog) {
|
|||
return Subs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Export
|
||||
/// @param filename
|
||||
/// @param charset
|
||||
|
@ -174,8 +155,6 @@ void AssExporter::Export(wxString filename, wxString charset, wxWindow *export_d
|
|||
Subs->Save(filename,false,false,charset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get window associated with name
|
||||
/// @param name
|
||||
/// @return
|
||||
|
@ -186,8 +165,6 @@ wxSizer *AssExporter::GetSettingsSizer(wxString name) {
|
|||
else return pos->second;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get description of filter
|
||||
/// @param name
|
||||
///
|
||||
|
@ -201,5 +178,3 @@ wxString AssExporter::GetDescription(wxString name) {
|
|||
}
|
||||
throw wxString::Format(_T("Filter not found: %s"), name.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace std {
|
|||
/// @brief AssFile constructor
|
||||
AssFile::AssFile ()
|
||||
: loaded(false)
|
||||
, commitId(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -109,16 +110,17 @@ void AssFile::Load (const wxString &_filename,wxString charset,bool addToRecent)
|
|||
|
||||
// Read file
|
||||
if (reader) {
|
||||
reader->SetTarget(this);
|
||||
AssFile temp;
|
||||
reader->SetTarget(&temp);
|
||||
reader->ReadFile(_filename,charset);
|
||||
swap(temp);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
// Couldn't find a type
|
||||
else throw _T("Unknown file type.");
|
||||
}
|
||||
|
||||
// String error
|
||||
catch (agi::UserCancelException const&) { }
|
||||
catch (const wchar_t *except) {
|
||||
wxMessageBox(except,_T("Error loading file"),wxICON_ERROR | wxOK);
|
||||
}
|
||||
|
@ -154,7 +156,7 @@ void AssFile::Load (const wxString &_filename,wxString charset,bool addToRecent)
|
|||
savedCommitId = commitId;
|
||||
|
||||
// Add to recent
|
||||
if (addToRecent) AddToRecent(_filename);
|
||||
if (addToRecent && ok) AddToRecent(_filename);
|
||||
}
|
||||
|
||||
void AssFile::Save(wxString _filename,bool setfilename,bool addToRecent,const wxString encoding) {
|
||||
|
|
|
@ -920,6 +920,16 @@ void AudioDisplay::SetFile(wxString file) {
|
|||
// Update
|
||||
UpdateImage();
|
||||
}
|
||||
catch (agi::UserCancelException const&) {
|
||||
return;
|
||||
}
|
||||
catch (agi::FileNotFoundError const& e) {
|
||||
config::mru->Remove("Audio", STD_STR(file));
|
||||
wxMessageBox(lagi_wxString(e.GetMessage()), L"Error loading audio",wxICON_ERROR | wxOK);
|
||||
}
|
||||
catch (AudioOpenError const& e) {
|
||||
wxMessageBox(lagi_wxString(e.GetMessage()), L"Error loading audio",wxICON_ERROR | wxOK);
|
||||
}
|
||||
catch (const wxChar *e) {
|
||||
if (player) { delete player; player = 0; }
|
||||
if (provider) { delete provider; provider = 0; }
|
||||
|
|
|
@ -34,16 +34,12 @@
|
|||
/// @ingroup audio_ui
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <algorithm>
|
||||
|
||||
#include <wx/dcclient.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/menu.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/tokenzr.h>
|
||||
|
@ -56,7 +52,6 @@
|
|||
#include "audio_display.h"
|
||||
#include "audio_karaoke.h"
|
||||
|
||||
|
||||
/// @brief Empty constructor
|
||||
///
|
||||
AudioKaraokeSyllable::AudioKaraokeSyllable()
|
||||
|
@ -66,7 +61,6 @@ AudioKaraokeSyllable::AudioKaraokeSyllable()
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
/// @brief Copy-from-base constructor
|
||||
/// @param base
|
||||
///
|
||||
|
@ -77,9 +71,6 @@ AudioKaraokeSyllable::AudioKaraokeSyllable(const AssKaraokeSyllable &base)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param parent
|
||||
///
|
||||
|
@ -95,16 +86,12 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent)
|
|||
workDiag = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
AudioKaraoke::~AudioKaraoke() {
|
||||
delete workDiag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Load from dialogue
|
||||
/// @param _diag
|
||||
/// @return
|
||||
|
@ -149,8 +136,6 @@ bool AudioKaraoke::LoadFromDialogue(AssDialogue *_diag) {
|
|||
return !hasKar;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Writes line back
|
||||
/// @return
|
||||
///
|
||||
|
@ -196,8 +181,6 @@ void AudioKaraoke::Commit() {
|
|||
LOG_D("karaoke/audio") << "returning";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Autosplit line
|
||||
/// @return
|
||||
///
|
||||
|
@ -253,8 +236,6 @@ void AudioKaraoke::AutoSplit() {
|
|||
LOG_D("karaoke/audio") << "returning";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Parses text to extract karaoke
|
||||
/// @param curDiag
|
||||
/// @return
|
||||
|
@ -287,8 +268,6 @@ bool AudioKaraoke::ParseDialogue(AssDialogue *curDiag) {
|
|||
return found_kara;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set syllable
|
||||
/// @param n
|
||||
/// @return
|
||||
|
@ -304,7 +283,6 @@ void AudioKaraoke::SetSyllable(int n) {
|
|||
LOG_D("karaoke/audio") << "returning";
|
||||
}
|
||||
|
||||
|
||||
///////////////
|
||||
// Event table
|
||||
BEGIN_EVENT_TABLE(AudioKaraoke,wxWindow)
|
||||
|
@ -313,8 +291,6 @@ BEGIN_EVENT_TABLE(AudioKaraoke,wxWindow)
|
|||
EVT_MOUSE_EVENTS(AudioKaraoke::OnMouse)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
|
||||
/// @brief Paint event
|
||||
/// @param event
|
||||
///
|
||||
|
@ -425,8 +401,6 @@ void AudioKaraoke::OnPaint(wxPaintEvent &event) {
|
|||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Size event
|
||||
/// @param event
|
||||
///
|
||||
|
@ -434,8 +408,6 @@ void AudioKaraoke::OnSize(wxSizeEvent &event) {
|
|||
Refresh(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Mouse event
|
||||
/// @param event
|
||||
/// @return
|
||||
|
@ -571,8 +543,6 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get Syllable at position X
|
||||
/// @param x
|
||||
/// @return
|
||||
|
@ -590,8 +560,6 @@ int AudioKaraoke::GetSylAtX(int x) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set selection
|
||||
/// @param start
|
||||
/// @param end
|
||||
|
@ -628,8 +596,6 @@ void AudioKaraoke::SetSelection(int start,int end) {
|
|||
box->SetKaraokeButtons();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Join syllables
|
||||
/// @return
|
||||
///
|
||||
|
@ -675,8 +641,6 @@ void AudioKaraoke::Join() {
|
|||
LOG_D("karaoke/audio") << "returning";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Enter splitting-mode
|
||||
///
|
||||
void AudioKaraoke::BeginSplit() {
|
||||
|
@ -688,8 +652,6 @@ void AudioKaraoke::BeginSplit() {
|
|||
Refresh(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Leave splitting-mode, committing changes
|
||||
/// @param commit
|
||||
/// @return
|
||||
|
@ -727,8 +689,6 @@ void AudioKaraoke::EndSplit(bool commit) {
|
|||
LOG_D("karaoke/audio") << "returning";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Split a syllable using the pending_slits data
|
||||
/// @param n
|
||||
/// @return
|
||||
|
@ -799,8 +759,6 @@ int AudioKaraoke::SplitSyl (unsigned int n) {
|
|||
return numsplits;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Apply delta length to syllable
|
||||
/// @param n
|
||||
/// @param delta
|
||||
|
@ -855,8 +813,6 @@ bool AudioKaraoke::SyllableDelta(int n,int delta,int mode) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Karaoke tag menu constructor
|
||||
/// @param _kara
|
||||
///
|
||||
|
@ -884,22 +840,17 @@ AudioKaraokeTagMenu::AudioKaraokeTagMenu(AudioKaraoke *_kara)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Karaoke tag menu destructor
|
||||
///
|
||||
AudioKaraokeTagMenu::~AudioKaraokeTagMenu() {
|
||||
}
|
||||
|
||||
|
||||
///////////////
|
||||
// Event table
|
||||
BEGIN_EVENT_TABLE(AudioKaraokeTagMenu,wxMenu)
|
||||
EVT_MENU_RANGE(10001, 10003, AudioKaraokeTagMenu::OnSelectItem)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
|
||||
/// @brief Karaoke tag menu event handler
|
||||
/// @param event
|
||||
///
|
||||
|
@ -934,6 +885,3 @@ void AudioKaraokeTagMenu::OnSelectItem(wxCommandEvent &event) {
|
|||
kara->SetSelection(firstsel, lastsel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -34,10 +34,8 @@
|
|||
/// @ingroup audio_output
|
||||
///
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifdef WITH_ALSA
|
||||
|
||||
#include <libaegisub/log.h>
|
||||
|
@ -48,7 +46,6 @@
|
|||
#include "frame_main.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
AlsaPlayer::AlsaPlayer()
|
||||
|
|
|
@ -34,16 +34,12 @@
|
|||
/// @ingroup audio_output
|
||||
///
|
||||
|
||||
|
||||
#ifdef WITH_ALSA
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "include/aegisub/audio_player.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class AlsaPlayer
|
||||
|
@ -62,7 +58,6 @@ private:
|
|||
/// DOCME
|
||||
volatile float volume;
|
||||
|
||||
|
||||
/// DOCME
|
||||
volatile unsigned long start_frame; // first frame of playback
|
||||
|
||||
|
@ -75,7 +70,6 @@ private:
|
|||
/// DOCME
|
||||
unsigned long bpf; // bytes per frame
|
||||
|
||||
|
||||
/// DOCME
|
||||
AudioProvider *provider;
|
||||
|
||||
|
@ -88,7 +82,6 @@ private:
|
|||
/// DOCME
|
||||
snd_async_handler_t *pcm_callback;
|
||||
|
||||
|
||||
/// DOCME
|
||||
snd_pcm_format_t sample_format;
|
||||
|
||||
|
@ -132,7 +125,6 @@ public:
|
|||
void SetEndPosition(int64_t pos);
|
||||
void SetCurrentPosition(int64_t pos);
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param vol
|
||||
/// @return
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup audio_output
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WITH_DIRECTSOUND
|
||||
|
@ -48,7 +45,6 @@
|
|||
#include "main.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
DirectSoundPlayer::DirectSoundPlayer() {
|
||||
|
@ -64,16 +60,12 @@ DirectSoundPlayer::DirectSoundPlayer() {
|
|||
thread = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
DirectSoundPlayer::~DirectSoundPlayer() {
|
||||
CloseStream();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Open stream
|
||||
///
|
||||
void DirectSoundPlayer::OpenStream() {
|
||||
|
@ -125,8 +117,6 @@ void DirectSoundPlayer::OpenStream() {
|
|||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Close stream
|
||||
///
|
||||
void DirectSoundPlayer::CloseStream() {
|
||||
|
@ -146,8 +136,6 @@ void DirectSoundPlayer::CloseStream() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Fill buffer
|
||||
/// @param fill
|
||||
/// @return
|
||||
|
@ -237,8 +225,6 @@ RetryLock:
|
|||
return playPos < endPos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Play
|
||||
/// @param start
|
||||
/// @param count
|
||||
|
@ -281,8 +267,6 @@ void DirectSoundPlayer::Play(int64_t start,int64_t count) {
|
|||
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Stop
|
||||
/// @param timerToo
|
||||
///
|
||||
|
@ -313,8 +297,6 @@ void DirectSoundPlayer::Stop(bool timerToo) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set end
|
||||
/// @param pos
|
||||
///
|
||||
|
@ -322,8 +304,6 @@ void DirectSoundPlayer::SetEndPosition(int64_t pos) {
|
|||
if (playing) endPos = pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set current position
|
||||
/// @param pos
|
||||
///
|
||||
|
@ -332,8 +312,6 @@ void DirectSoundPlayer::SetCurrentPosition(int64_t pos) {
|
|||
startTime = GetTickCount();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get current position
|
||||
/// @return
|
||||
///
|
||||
|
@ -348,8 +326,6 @@ int64_t DirectSoundPlayer::GetCurrentPosition() {
|
|||
return startPos + tdiff * provider->GetSampleRate() / 1000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Thread constructor
|
||||
/// @param par
|
||||
///
|
||||
|
@ -358,16 +334,12 @@ DirectSoundPlayerThread::DirectSoundPlayerThread(DirectSoundPlayer *par) : wxThr
|
|||
stopnotify = CreateEvent(NULL, true, false, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Thread destructor
|
||||
///
|
||||
DirectSoundPlayerThread::~DirectSoundPlayerThread() {
|
||||
CloseHandle(stopnotify);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Thread entry point
|
||||
/// @return
|
||||
///
|
||||
|
@ -418,8 +390,6 @@ wxThread::ExitCode DirectSoundPlayerThread::Entry() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Stop playback thread
|
||||
///
|
||||
void DirectSoundPlayerThread::Stop() {
|
||||
|
@ -429,4 +399,3 @@ void DirectSoundPlayerThread::Stop() {
|
|||
|
||||
#endif // WITH_DIRECTSOUND
|
||||
|
||||
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup audio_output
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#ifdef WITH_DIRECTSOUND
|
||||
|
||||
#ifndef AGI_PRE
|
||||
|
@ -47,15 +44,9 @@
|
|||
|
||||
#include "include/aegisub/audio_player.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class DirectSoundPlayer;
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class DirectSoundPlayerThread
|
||||
/// @brief DOCME
|
||||
|
@ -93,8 +84,6 @@ detect which were actually changed and act accordingly.
|
|||
All but GetPosition() set appropriate fields and then raise the parameters changed event.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class DirectSoundPlayer
|
||||
/// @brief DOCME
|
||||
|
@ -117,7 +106,6 @@ private:
|
|||
/// DOCME
|
||||
DWORD bufSize;
|
||||
|
||||
|
||||
/// DOCME
|
||||
volatile int64_t playPos;
|
||||
|
||||
|
@ -130,7 +118,6 @@ private:
|
|||
/// DOCME
|
||||
DWORD startTime;
|
||||
|
||||
|
||||
/// DOCME
|
||||
IDirectSound8 *directSound;
|
||||
|
||||
|
@ -139,7 +126,6 @@ private:
|
|||
|
||||
bool FillBuffer(bool fill);
|
||||
|
||||
|
||||
/// DOCME
|
||||
DirectSoundPlayerThread *thread;
|
||||
|
||||
|
@ -158,7 +144,6 @@ public:
|
|||
///
|
||||
bool IsPlaying() { return playing; }
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -172,7 +157,6 @@ public:
|
|||
void SetEndPosition(int64_t pos);
|
||||
void SetCurrentPosition(int64_t pos);
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param vol
|
||||
/// @return
|
||||
|
|
|
@ -44,17 +44,6 @@
|
|||
#include "frame_main.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <al.h>
|
||||
#include <alc.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <OpenAL/AL.h>
|
||||
#include <OpenAL/ALC.h>
|
||||
#else
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#endif
|
||||
|
||||
// Auto-link to OpenAL lib for MSVC
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "openal32.lib")
|
||||
|
@ -78,8 +67,6 @@ OpenALPlayer::~OpenALPlayer()
|
|||
CloseStream();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Open stream
|
||||
///
|
||||
void OpenALPlayer::OpenStream()
|
||||
|
@ -135,8 +122,6 @@ void OpenALPlayer::OpenStream()
|
|||
open = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Close stream
|
||||
/// @return
|
||||
///
|
||||
|
@ -155,8 +140,6 @@ void OpenALPlayer::CloseStream()
|
|||
open = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Play
|
||||
/// @param start
|
||||
/// @param count
|
||||
|
@ -192,8 +175,6 @@ void OpenALPlayer::Play(int64_t start,int64_t count)
|
|||
if (displayTimer && !displayTimer->IsRunning()) displayTimer->Start(15);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Stop
|
||||
/// @param timerToo
|
||||
/// @return
|
||||
|
@ -219,8 +200,6 @@ void OpenALPlayer::Stop(bool timerToo)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param count
|
||||
///
|
||||
|
@ -261,8 +240,6 @@ void OpenALPlayer::FillBuffers(ALsizei count)
|
|||
free(data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
///
|
||||
void OpenALPlayer::Notify()
|
||||
|
@ -300,8 +277,6 @@ void OpenALPlayer::Notify()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -310,8 +285,6 @@ bool OpenALPlayer::IsPlaying()
|
|||
return playing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set end
|
||||
/// @param pos
|
||||
///
|
||||
|
@ -320,8 +293,6 @@ void OpenALPlayer::SetEndPosition(int64_t pos)
|
|||
end_frame = pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set current position
|
||||
/// @param pos
|
||||
///
|
||||
|
@ -330,8 +301,6 @@ void OpenALPlayer::SetCurrentPosition(int64_t pos)
|
|||
cur_frame = pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -340,8 +309,6 @@ int64_t OpenALPlayer::GetStartPosition()
|
|||
return start_frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -350,8 +317,6 @@ int64_t OpenALPlayer::GetEndPosition()
|
|||
return end_frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get current position
|
||||
///
|
||||
int64_t OpenALPlayer::GetCurrentPosition()
|
||||
|
@ -362,5 +327,4 @@ int64_t OpenALPlayer::GetCurrentPosition()
|
|||
return buffers_played * buffer_length + start_frame + extra * samplerate / 1000;
|
||||
}
|
||||
|
||||
|
||||
#endif // WITH_OPENAL
|
||||
|
|
|
@ -34,11 +34,9 @@
|
|||
/// @ingroup audio_output
|
||||
///
|
||||
|
||||
|
||||
#ifdef WITH_OPENAL
|
||||
#include "include/aegisub/audio_player.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include <al.h>
|
||||
|
@ -68,7 +66,6 @@ private:
|
|||
/// DOCME
|
||||
volatile float volume;
|
||||
|
||||
|
||||
/// DOCME
|
||||
static const ALsizei num_buffers = 8;
|
||||
|
||||
|
@ -78,7 +75,6 @@ private:
|
|||
/// DOCME
|
||||
ALsizei samplerate;
|
||||
|
||||
|
||||
/// DOCME
|
||||
volatile unsigned long start_frame; // first frame of playback
|
||||
|
||||
|
@ -91,7 +87,6 @@ private:
|
|||
/// DOCME
|
||||
unsigned long bpf; // bytes per frame
|
||||
|
||||
|
||||
/// DOCME
|
||||
AudioProvider *provider;
|
||||
|
||||
|
@ -107,7 +102,6 @@ private:
|
|||
/// DOCME
|
||||
ALuint source; // playback source
|
||||
|
||||
|
||||
/// DOCME
|
||||
ALsizei buf_first_free; // index into buffers, first free (unqueued) buffer
|
||||
|
||||
|
@ -145,7 +139,6 @@ public:
|
|||
void SetEndPosition(int64_t pos);
|
||||
void SetCurrentPosition(int64_t pos);
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param vol
|
||||
/// @return
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
/// @ingroup audio_output
|
||||
///
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WITH_OSS
|
||||
|
@ -45,7 +44,6 @@
|
|||
#include "main.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
OSSPlayer::OSSPlayer()
|
||||
|
@ -58,8 +56,6 @@ OSSPlayer::OSSPlayer()
|
|||
thread = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
OSSPlayer::~OSSPlayer()
|
||||
|
@ -67,8 +63,6 @@ OSSPlayer::~OSSPlayer()
|
|||
CloseStream();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Open stream
|
||||
///
|
||||
void OSSPlayer::OpenStream()
|
||||
|
@ -125,8 +119,6 @@ void OSSPlayer::OpenStream()
|
|||
open = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Close stream
|
||||
/// @return
|
||||
///
|
||||
|
@ -141,8 +133,6 @@ void OSSPlayer::CloseStream()
|
|||
open = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Play
|
||||
/// @param start
|
||||
/// @param count
|
||||
|
@ -163,8 +153,6 @@ void OSSPlayer::Play(int64_t start, int64_t count)
|
|||
playing = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Stop
|
||||
/// @param timerToo
|
||||
/// @return
|
||||
|
@ -198,8 +186,6 @@ void OSSPlayer::Stop(bool timerToo)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -208,8 +194,6 @@ bool OSSPlayer::IsPlaying()
|
|||
return playing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set end
|
||||
/// @param pos
|
||||
///
|
||||
|
@ -225,8 +209,6 @@ void OSSPlayer::SetEndPosition(int64_t pos)
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set current position
|
||||
/// @param pos
|
||||
///
|
||||
|
@ -235,8 +217,6 @@ void OSSPlayer::SetCurrentPosition(int64_t pos)
|
|||
cur_frame = start_frame = pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -245,8 +225,6 @@ int64_t OSSPlayer::GetStartPosition()
|
|||
return start_frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -255,8 +233,6 @@ int64_t OSSPlayer::GetEndPosition()
|
|||
return end_frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get current position
|
||||
/// @return
|
||||
///
|
||||
|
@ -305,8 +281,6 @@ int64_t OSSPlayer::GetCurrentPosition()
|
|||
return cur_frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Thread constructor
|
||||
/// @param par
|
||||
///
|
||||
|
@ -338,6 +312,4 @@ wxThread::ExitCode OSSPlayerThread::Entry() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // WITH_OSS
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
|
||||
#include "include/aegisub/audio_player.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "utils.h"
|
||||
|
||||
class OSSPlayer;
|
||||
|
||||
|
@ -73,8 +72,6 @@ public:
|
|||
wxThread::ExitCode Entry();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class OSSPlayer
|
||||
/// @brief DOCME
|
||||
|
|
|
@ -34,13 +34,13 @@
|
|||
/// @ingroup audio_output
|
||||
///
|
||||
|
||||
|
||||
#ifdef WITH_PORTAUDIO
|
||||
|
||||
#include "include/aegisub/audio_player.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "utils.h"
|
||||
extern "C" {
|
||||
|
||||
|
||||
"C" {
|
||||
#include <portaudio.h>
|
||||
}
|
||||
|
||||
|
|
|
@ -35,15 +35,10 @@
|
|||
///
|
||||
|
||||
#ifdef WITH_PULSEAUDIO
|
||||
#ifndef AGI_PRE
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#include "include/aegisub/audio_player.h"
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "utils.h"
|
||||
|
||||
class PulseAudioPlayer;
|
||||
|
||||
|
|
|
@ -178,65 +178,68 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count,
|
|||
///
|
||||
AudioProvider *AudioProviderFactory::GetProvider(wxString filename, int cache) {
|
||||
AudioProvider *provider = NULL;
|
||||
bool found = false;
|
||||
std::string msg;
|
||||
|
||||
if (!OPT_GET("Provider/Audio/PCM/Disable")->GetBool()) {
|
||||
// Try a PCM provider first
|
||||
try {
|
||||
provider = CreatePCMAudioProvider(filename);
|
||||
if (provider) {
|
||||
if (provider->GetBytesPerSample() == 2 && provider->GetSampleRate() >= 32000 && provider->GetChannels() == 1)
|
||||
return provider;
|
||||
else {
|
||||
return CreateConvertAudioProvider(provider);
|
||||
}
|
||||
catch (agi::FileNotFoundError const& err) {
|
||||
msg = "PCM audio provider: " + err.GetMessage() + " not found.\n";
|
||||
}
|
||||
catch (AudioOpenError const& err) {
|
||||
found = true;
|
||||
msg += err.GetMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List of providers
|
||||
if (!provider) {
|
||||
std::vector<std::string> list = GetClasses(OPT_GET("Audio/Provider")->GetString());
|
||||
if (list.empty()) throw AudioOpenError("No audio providers are available.");
|
||||
|
||||
if (list.empty()) throw _T("No audio providers are available.");
|
||||
|
||||
// Get provider
|
||||
wxString error;
|
||||
for (unsigned int i=0;i<list.size();i++) {
|
||||
try {
|
||||
provider = Create(list[i], filename);
|
||||
if (provider) break;
|
||||
}
|
||||
catch (wxString err) { error += list[i] + _T(" factory: ") + err + _T("\n"); }
|
||||
catch (const wxChar *err) { error += list[i] + _T(" factory: ") + wxString(err) + _T("\n"); }
|
||||
catch (...) { error += list[i] + _T(" factory: Unknown error\n"); }
|
||||
catch (agi::FileNotFoundError const& err) {
|
||||
msg += list[i] + ": " + err.GetMessage() + " not found.\n";
|
||||
}
|
||||
catch (AudioOpenError const& err) {
|
||||
found = true;
|
||||
msg += list[i] + ": " + err.GetMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!provider) {
|
||||
if (found) {
|
||||
throw AudioOpenError(msg);
|
||||
}
|
||||
else {
|
||||
throw agi::FileNotFoundError(STD_STR(filename));
|
||||
}
|
||||
}
|
||||
bool needsCache = provider->NeedsCache();
|
||||
|
||||
// Failed
|
||||
if (!provider) throw error;
|
||||
|
||||
// Give it a conversor if needed
|
||||
// Give it a converter if needed
|
||||
if (provider->GetBytesPerSample() != 2 || provider->GetSampleRate() < 32000 || provider->GetChannels() != 1)
|
||||
provider = CreateConvertAudioProvider(provider);
|
||||
|
||||
// Change provider to RAM/HD cache if needed
|
||||
if (cache == -1) cache = OPT_GET("Audio/Cache/Type")->GetInt();
|
||||
if (cache) {
|
||||
AudioProvider *final = NULL;
|
||||
|
||||
// Convert to RAM
|
||||
if (cache == 1) final = new RAMAudioProvider(provider);
|
||||
|
||||
// Convert to HD
|
||||
if (cache == 2) final = new HDAudioProvider(provider);
|
||||
|
||||
// Reassign
|
||||
if (final) {
|
||||
delete provider;
|
||||
return final;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cache || !needsCache) {
|
||||
return provider;
|
||||
}
|
||||
|
||||
// Convert to RAM
|
||||
if (cache == 1) return new RAMAudioProvider(provider);
|
||||
|
||||
// Convert to HD
|
||||
if (cache == 2) return new HDAudioProvider(provider);
|
||||
|
||||
throw AudioOpenError("Unknown caching method");
|
||||
}
|
||||
|
||||
/// @brief Register all providers
|
||||
///
|
||||
|
|
|
@ -34,14 +34,10 @@
|
|||
/// @ingroup audio_input
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WITH_AVISYNTH
|
||||
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <Mmreg.h>
|
||||
#include <time.h>
|
||||
|
@ -56,61 +52,25 @@
|
|||
#include "standard_paths.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param _filename
|
||||
///
|
||||
AvisynthAudioProvider::AvisynthAudioProvider(wxString _filename) {
|
||||
filename = _filename;
|
||||
|
||||
try {
|
||||
OpenAVSAudio();
|
||||
}
|
||||
catch (...) {
|
||||
Unload();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
AvisynthAudioProvider::~AvisynthAudioProvider() {
|
||||
Unload();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Unload audio
|
||||
///
|
||||
void AvisynthAudioProvider::Unload() {
|
||||
// Clean up avisynth
|
||||
clip = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Load audio from avisynth
|
||||
///
|
||||
void AvisynthAudioProvider::OpenAVSAudio() {
|
||||
// Set variables
|
||||
AvisynthAudioProvider::AvisynthAudioProvider(wxString filename) try : filename(filename) {
|
||||
AVSValue script;
|
||||
|
||||
// Prepare avisynth
|
||||
wxMutexLocker lock(AviSynthMutex);
|
||||
|
||||
try {
|
||||
wxFileName fn(filename);
|
||||
if (!fn.FileExists())
|
||||
throw agi::FileNotFoundError(STD_STR(filename));
|
||||
|
||||
// Include
|
||||
if (filename.EndsWith(_T(".avs"))) {
|
||||
wxFileName fn(filename);
|
||||
char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal));
|
||||
script = env->Invoke("Import", fname);
|
||||
}
|
||||
|
||||
// Use DirectShowSource
|
||||
else {
|
||||
wxFileName fn(filename);
|
||||
const char * argnames[3] = { 0, "video", "audio" };
|
||||
AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true };
|
||||
|
||||
|
@ -126,30 +86,25 @@ void AvisynthAudioProvider::OpenAVSAudio() {
|
|||
}
|
||||
// Otherwise fail
|
||||
else {
|
||||
throw AvisynthError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.");
|
||||
throw AudioOpenError("No suitable audio source filter found. Try placing DirectShowSource.dll in the Aegisub application directory.");
|
||||
}
|
||||
}
|
||||
|
||||
LoadFromClip(script);
|
||||
}
|
||||
|
||||
catch (AvisynthError &err) {
|
||||
throw wxString::Format(_T("AviSynth error: %s"), wxString(err.msg,csConvLocal));
|
||||
throw AudioOpenError("Avisynth error: " + std::string(err.msg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Read from environment
|
||||
/// @param _clip
|
||||
///
|
||||
void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) {
|
||||
// Prepare avisynth
|
||||
AVSValue script;
|
||||
|
||||
// Check if it has audio
|
||||
VideoInfo vi = _clip.AsClip()->GetVideoInfo();
|
||||
if (!vi.HasAudio()) throw wxString(_T("No audio found."));
|
||||
if (!vi.HasAudio()) throw AudioOpenError("No audio found.");
|
||||
|
||||
// Convert to one channel
|
||||
char buffer[1024];
|
||||
|
@ -178,20 +133,9 @@ void AvisynthAudioProvider::LoadFromClip(AVSValue _clip) {
|
|||
sample_rate = vi.SamplesPerSecond();
|
||||
bytes_per_sample = vi.BytesPerAudioSample();
|
||||
|
||||
// Set
|
||||
clip = tempclip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get filename
|
||||
/// @return
|
||||
///
|
||||
wxString AvisynthAudioProvider::GetFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Get audio
|
||||
/// @param buf
|
||||
/// @param start
|
||||
|
@ -223,7 +167,4 @@ void AvisynthAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
|||
clip->GetAudio(buf,start,count,env);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
///
|
||||
|
||||
#ifdef WITH_AVISYNTH
|
||||
#include <Mmreg.h>
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
#include "avisynth_wrap.h"
|
||||
|
||||
|
@ -46,8 +45,6 @@
|
|||
///
|
||||
/// DOCME
|
||||
class AvisynthAudioProvider : public AudioProvider, public AviSynthWrapper {
|
||||
private:
|
||||
|
||||
/// DOCME
|
||||
wxString filename;
|
||||
|
||||
|
@ -55,21 +52,18 @@ private:
|
|||
PClip clip;
|
||||
|
||||
void LoadFromClip(AVSValue clip);
|
||||
void OpenAVSAudio();
|
||||
void SetFile();
|
||||
void Unload();
|
||||
|
||||
public:
|
||||
AvisynthAudioProvider(wxString _filename);
|
||||
~AvisynthAudioProvider();
|
||||
|
||||
wxString GetFilename();
|
||||
|
||||
wxString GetFilename() { return filename; }
|
||||
|
||||
/// @brief Only exists for x86 Windows, always delivers machine (little) endian
|
||||
/// @return
|
||||
///
|
||||
bool AreSamplesNativeEndian() const { return true; }
|
||||
bool NeedsCache() const { return true; }
|
||||
|
||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||
void GetWaveForm(int *min,int *peak,int64_t start,int w,int h,int samples,float scale);
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup audio_input
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "aegisub_endian.h"
|
||||
|
@ -47,8 +44,7 @@
|
|||
/// @brief Constructor
|
||||
/// @param src
|
||||
///
|
||||
ConvertAudioProvider::ConvertAudioProvider(AudioProvider *src) {
|
||||
source = src;
|
||||
ConvertAudioProvider::ConvertAudioProvider(AudioProvider *src) : source(src) {
|
||||
channels = source->GetChannels();
|
||||
num_samples = source->GetNumSamples();
|
||||
sample_rate = source->GetSampleRate();
|
||||
|
@ -61,16 +57,6 @@ ConvertAudioProvider::ConvertAudioProvider(AudioProvider *src) {
|
|||
num_samples *= sampleMult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
ConvertAudioProvider::~ConvertAudioProvider() {
|
||||
delete source;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Convert to 16-bit
|
||||
/// @param src
|
||||
/// @param dst
|
||||
|
@ -82,7 +68,6 @@ void ConvertAudioProvider::Make16Bit(const char *src, short *dst, int64_t count)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////
|
||||
// Change sample rate
|
||||
// This requres 16-bit input
|
||||
|
@ -134,35 +119,21 @@ void ConvertAudioProvider::ChangeSampleRate(const short *src, short *dst, int64_
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
struct NullSampleConverter {
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param val
|
||||
/// @return
|
||||
///
|
||||
inline short operator()(const short val) const {
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// DOCME
|
||||
struct EndianSwapSampleConverter {
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param val
|
||||
/// @return
|
||||
///
|
||||
inline short operator()(const short val) const {
|
||||
return (short)Endian::Reverse((uint16_t)val);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// @brief Get audio
|
||||
/// @param destination
|
||||
/// @param start
|
||||
|
@ -234,7 +205,7 @@ AudioProvider *CreateConvertAudioProvider(AudioProvider *source_provider) {
|
|||
{
|
||||
// @todo add support for more bitdepths (i.e. 24- and 32-bit audio)
|
||||
if (provider->GetBytesPerSample() > 2)
|
||||
throw _T("Audio format converter: audio with bitdepths greater than 16 bits/sample is currently unsupported");
|
||||
AudioOpenError("Audio format converter: audio with bitdepths greater than 16 bits/sample is currently unsupported");
|
||||
|
||||
provider = new ConvertAudioProvider(provider);
|
||||
}
|
||||
|
@ -247,5 +218,3 @@ AudioProvider *CreateConvertAudioProvider(AudioProvider *source_provider) {
|
|||
|
||||
return provider;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <tr1/memory>
|
||||
#endif
|
||||
|
||||
/// DOCME
|
||||
/// @class ConvertAudioProvider
|
||||
|
@ -43,32 +46,24 @@
|
|||
///
|
||||
/// DOCME
|
||||
class ConvertAudioProvider : public AudioProvider {
|
||||
private:
|
||||
|
||||
/// DOCME
|
||||
int sampleMult;
|
||||
|
||||
|
||||
/// DOCME
|
||||
AudioProvider *source;
|
||||
std::tr1::shared_ptr<AudioProvider> source;
|
||||
void Make16Bit(const char *src, short *dst, int64_t count);
|
||||
template<class SampleConverter>
|
||||
void ChangeSampleRate(const short *src, short *dst, int64_t count, const SampleConverter &converter);
|
||||
|
||||
public:
|
||||
ConvertAudioProvider(AudioProvider *source);
|
||||
~ConvertAudioProvider();
|
||||
|
||||
|
||||
/// @brief // That's one of the points of it! // By its nature, the ConvertAudioProvider always delivers machine endian:
|
||||
/// @return
|
||||
///
|
||||
/// By its nature, the ConvertAudioProvider always delivers machine endian.
|
||||
/// That's one of the points of it!
|
||||
bool AreSamplesNativeEndian() const { return true; }
|
||||
|
||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||
|
||||
/// @brief DOCME
|
||||
///
|
||||
wxString GetFilename() { return source->GetFilename(); }
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
/// @brief Constructor
|
||||
/// @param source
|
||||
///
|
||||
DownmixingAudioProvider::DownmixingAudioProvider(AudioProvider *source) {
|
||||
DownmixingAudioProvider::DownmixingAudioProvider(AudioProvider *source) : provider(source) {
|
||||
filename = source->GetFilename();
|
||||
channels = 1; // target
|
||||
src_channels = source->GetChannels();
|
||||
|
@ -53,23 +53,12 @@ DownmixingAudioProvider::DownmixingAudioProvider(AudioProvider *source) {
|
|||
bytes_per_sample = source->GetBytesPerSample();
|
||||
sample_rate = source->GetSampleRate();
|
||||
|
||||
// We now own this
|
||||
provider = source;
|
||||
|
||||
if (!(bytes_per_sample == 1 || bytes_per_sample == 2))
|
||||
throw _T("Downmixing Audio Provider: Can only downmix 8 and 16 bit audio");
|
||||
throw AudioOpenError("Downmixing Audio Provider: Can only downmix 8 and 16 bit audio");
|
||||
if (!source->AreSamplesNativeEndian())
|
||||
throw _T("Downmixing Audio Provider: Source must have machine endian samples");
|
||||
throw AudioOpenError("Downmixing Audio Provider: Source must have machine endian samples");
|
||||
}
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
DownmixingAudioProvider::~DownmixingAudioProvider() {
|
||||
delete provider;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Actual work happens here
|
||||
/// @param buf
|
||||
/// @param start
|
||||
|
@ -95,7 +84,13 @@ void DownmixingAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
|||
// a pre-allocced block of memory...?
|
||||
char *tmp = new char[count*bytes_per_sample*src_channels];
|
||||
|
||||
try {
|
||||
provider->GetAudio(tmp, start, count);
|
||||
}
|
||||
catch (...) {
|
||||
delete tmp;
|
||||
throw;
|
||||
}
|
||||
|
||||
// Now downmix
|
||||
// Just average the samples over the channels (really bad if they're out of phase!)
|
||||
|
@ -128,5 +123,3 @@ void DownmixingAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
|||
// Done downmixing, free the work buffer
|
||||
delete[] tmp;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,9 +34,11 @@
|
|||
/// @ingroup audio_input
|
||||
///
|
||||
|
||||
|
||||
#include "include/aegisub/audio_provider.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <tr1/memory>
|
||||
#endif
|
||||
|
||||
/// DOCME
|
||||
/// @class DownmixingAudioProvider
|
||||
|
@ -44,20 +46,14 @@
|
|||
///
|
||||
/// DOCME
|
||||
class DownmixingAudioProvider : public AudioProvider {
|
||||
private:
|
||||
|
||||
/// DOCME
|
||||
AudioProvider *provider;
|
||||
std::tr1::shared_ptr<AudioProvider> provider;
|
||||
|
||||
/// DOCME
|
||||
int src_channels;
|
||||
|
||||
public:
|
||||
DownmixingAudioProvider(AudioProvider *source);
|
||||
~DownmixingAudioProvider();
|
||||
|
||||
|
||||
/// @brief // Downmixing requires samples to be native endian beforehand
|
||||
/// @brief Downmixing requires samples to be native endian beforehand
|
||||
///
|
||||
bool AreSamplesNativeEndian() const { return true; }
|
||||
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup audio_input
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "audio_provider_dummy.h"
|
||||
|
@ -55,15 +52,11 @@ DummyAudioProvider::DummyAudioProvider(unsigned long dur_ms, bool _noise) {
|
|||
num_samples = (int64_t)dur_ms * sample_rate / 1000;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
DummyAudioProvider::~DummyAudioProvider() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get audio
|
||||
/// @param buf
|
||||
/// @param start
|
||||
|
@ -81,5 +74,3 @@ void DummyAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
|||
*workbuf++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,8 +42,6 @@
|
|||
///
|
||||
/// DOCME
|
||||
class DummyAudioProvider : public AudioProvider {
|
||||
private:
|
||||
|
||||
/// DOCME
|
||||
bool noise;
|
||||
|
||||
|
@ -51,10 +49,6 @@ public:
|
|||
DummyAudioProvider(unsigned long dur_ms, bool _noise);
|
||||
~DummyAudioProvider();
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
///
|
||||
bool AreSamplesNativeEndian() const { return true; }
|
||||
|
||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||
};
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
#ifdef WITH_FFMPEGSOURCE
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#ifndef AGI_PRE
|
||||
#ifdef WIN32
|
||||
#include <objbase.h>
|
||||
|
@ -49,22 +47,24 @@
|
|||
#endif
|
||||
|
||||
#include "audio_provider_ffmpegsource.h"
|
||||
#include "include/aegisub/aegisub.h"
|
||||
#include "compat.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param filename
|
||||
///
|
||||
FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) {
|
||||
COMInited = false;
|
||||
FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename)
|
||||
: AudioSource(NULL)
|
||||
, COMInited(false)
|
||||
{
|
||||
#ifdef WIN32
|
||||
HRESULT res;
|
||||
res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
if (SUCCEEDED(res))
|
||||
COMInited = true;
|
||||
else if (res != RPC_E_CHANGED_MODE)
|
||||
throw _T("FFmpegSource video provider: COM initialization failure");
|
||||
throw AudioOpenError("COM initialization failure");
|
||||
#endif
|
||||
FFMS_Init(0);
|
||||
|
||||
|
@ -72,10 +72,6 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) {
|
|||
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
||||
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
||||
ErrorMsg = _T("FFmpegSource audio provider: ");
|
||||
|
||||
AudioSource = NULL;
|
||||
|
||||
SetLogLevel();
|
||||
|
||||
try {
|
||||
|
@ -86,28 +82,20 @@ FFmpegSourceAudioProvider::FFmpegSourceAudioProvider(wxString filename) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Load audio file
|
||||
/// @param filename
|
||||
///
|
||||
void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
||||
// clean up
|
||||
Close();
|
||||
|
||||
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
||||
|
||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
||||
if (Indexer == NULL) {
|
||||
// error messages that can possibly contain a filename use this method instead of
|
||||
// wxString::Format because they may contain utf8 characters
|
||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
||||
throw ErrorMsg;
|
||||
throw agi::FileNotFoundError(ErrInfo.Buffer);
|
||||
}
|
||||
|
||||
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_AUDIO);
|
||||
if (TrackList.size() <= 0)
|
||||
throw _T("FFmpegSource audio provider: no audio tracks found");
|
||||
throw AudioOpenError("no audio tracks found");
|
||||
|
||||
// initialize the track number to an invalid value so we can detect later on
|
||||
// whether the user actually had to choose a track or not
|
||||
|
@ -116,7 +104,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
|||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_AUDIO);
|
||||
// if it's still -1 here, user pressed cancel
|
||||
if (TrackNumber == -1)
|
||||
throw _T("FFmpegSource audio provider: audio loading cancelled by user");
|
||||
throw agi::UserCancelException("audio loading cancelled by user");
|
||||
}
|
||||
|
||||
// generate a name for the cache file
|
||||
|
@ -143,8 +131,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
|||
if (TrackNumber < 0) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any audio tracks: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw AudioOpenError(std::string("Couldn't find any audio tracks: ") + ErrInfo.Buffer);
|
||||
}
|
||||
|
||||
// index is valid and track number is now set,
|
||||
|
@ -171,11 +158,9 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
|||
|
||||
try {
|
||||
Index = DoIndexing(Indexer, CacheName, TrackMask, GetErrorHandlingMode());
|
||||
} catch (wxString temp) {
|
||||
ErrorMsg.Append(temp);
|
||||
throw ErrorMsg;
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
catch (wxString const& err) {
|
||||
throw AudioOpenError(STD_STR(err));
|
||||
}
|
||||
|
||||
// if tracknumber still isn't set we need to set it now
|
||||
|
@ -192,8 +177,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
|||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
if (!AudioSource) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to open audio track: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw AudioOpenError(std::string("Failed to open audio track: %s") + ErrInfo.Buffer);
|
||||
}
|
||||
|
||||
const FFMS_AudioProperties AudioInfo = *FFMS_GetAudioProperties(AudioSource);
|
||||
|
@ -202,7 +186,7 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
|||
sample_rate = AudioInfo.SampleRate;
|
||||
num_samples = AudioInfo.NumSamples;
|
||||
if (channels <= 0 || sample_rate <= 0 || num_samples <= 0)
|
||||
throw _T("FFmpegSource audio provider: sanity check failed, consult your local psychiatrist");
|
||||
throw AudioOpenError("sanity check failed, consult your local psychiatrist");
|
||||
|
||||
// FIXME: use the actual sample format too?
|
||||
// why not just bits_per_sample/8? maybe there's some oddball format with half bytes out there somewhere...
|
||||
|
@ -212,33 +196,26 @@ void FFmpegSourceAudioProvider::LoadAudio(wxString filename) {
|
|||
case 24: bytes_per_sample = 3; break;
|
||||
case 32: bytes_per_sample = 4; break;
|
||||
default:
|
||||
throw _T("FFmpegSource audio provider: unknown or unsupported sample format");
|
||||
throw AudioOpenError("unknown or unsupported sample format");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
FFmpegSourceAudioProvider::~FFmpegSourceAudioProvider() {
|
||||
Close();
|
||||
}
|
||||
|
||||
/// @brief Clean up
|
||||
///
|
||||
void FFmpegSourceAudioProvider::Close() {
|
||||
if (AudioSource) FFMS_DestroyAudioSource(AudioSource);
|
||||
#ifdef WIN32
|
||||
if (COMInited)
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Clean up
|
||||
///
|
||||
void FFmpegSourceAudioProvider::Close() {
|
||||
FFMS_DestroyAudioSource(AudioSource);
|
||||
AudioSource = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get audio
|
||||
/// @param Buf
|
||||
/// @param Start
|
||||
|
@ -246,12 +223,7 @@ void FFmpegSourceAudioProvider::Close() {
|
|||
///
|
||||
void FFmpegSourceAudioProvider::GetAudio(void *Buf, int64_t Start, int64_t Count) {
|
||||
if (FFMS_GetAudio(AudioSource, Buf, Start, Count, &ErrInfo)) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to get audio samples: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw AudioDecodeError(std::string("Failed to get audio samples: ") + ErrInfo.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* WITH_FFMPEGSOURCE */
|
||||
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
|
||||
/// @class FFmpegSourceAudioProvider
|
||||
/// @brief Implents audio loading with the FFMS library.
|
||||
/// @brief Implements audio loading with the FFMS library.
|
||||
class FFmpegSourceAudioProvider : public AudioProvider, FFmpegSourceProvider {
|
||||
private:
|
||||
FFMS_AudioSource *AudioSource; /// audio source object
|
||||
|
@ -48,7 +48,6 @@ private:
|
|||
|
||||
char FFMSErrMsg[1024]; /// FFMS error message
|
||||
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
||||
wxString ErrorMsg; /// wx-ified error message
|
||||
|
||||
void Close();
|
||||
void LoadAudio(wxString filename);
|
||||
|
@ -61,6 +60,7 @@ public:
|
|||
/// @return Returns true.
|
||||
/// FFMS always delivers native endian samples.
|
||||
bool AreSamplesNativeEndian() const { return true; }
|
||||
bool NeedsCache() const { return true; }
|
||||
|
||||
virtual void GetAudio(void *buf, int64_t start, int64_t count);
|
||||
};
|
||||
|
|
|
@ -34,14 +34,9 @@
|
|||
/// @ingroup audio_input
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <wx/file.h>
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/filename.h>
|
||||
#endif
|
||||
|
@ -54,11 +49,11 @@
|
|||
#include "standard_paths.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param source
|
||||
///
|
||||
HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
||||
HDAudioProvider::HDAudioProvider(AudioProvider *src) {
|
||||
std::auto_ptr<AudioProvider> source(src);
|
||||
// Copy parameters
|
||||
bytes_per_sample = source->GetBytesPerSample();
|
||||
num_samples = source->GetNumSamples();
|
||||
|
@ -71,7 +66,7 @@ HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
|||
wxLongLong freespace;
|
||||
if (wxGetDiskSpace(DiskCachePath(), NULL, &freespace)) {
|
||||
if (num_samples * channels * bytes_per_sample > freespace) {
|
||||
throw wxString(_T("Not enough free disk space in "))+DiskCachePath()+wxString(_T(" to cache the audio"));
|
||||
throw AudioOpenError("Not enough free disk space in " + STD_STR(DiskCachePath()) + " to cache the audio");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +74,7 @@ HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
|||
diskCacheFilename = DiskCacheName();
|
||||
file_cache.Create(diskCacheFilename,true,wxS_DEFAULT);
|
||||
file_cache.Open(diskCacheFilename,wxFile::read_write);
|
||||
if (!file_cache.IsOpened()) throw _T("Unable to write to audio disk cache.");
|
||||
if (!file_cache.IsOpened()) throw AudioOpenError("Unable to write to audio disk cache.");
|
||||
|
||||
// Start progress
|
||||
volatile bool canceled = false;
|
||||
|
@ -102,12 +97,10 @@ HDAudioProvider::HDAudioProvider(AudioProvider *source) {
|
|||
if (canceled) {
|
||||
file_cache.Close();
|
||||
delete[] data;
|
||||
throw wxString(_T("Audio loading cancelled by user"));
|
||||
throw agi::UserCancelException("Audio loading cancelled by user");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
HDAudioProvider::~HDAudioProvider() {
|
||||
|
@ -116,8 +109,6 @@ HDAudioProvider::~HDAudioProvider() {
|
|||
delete[] data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get audio
|
||||
/// @param buf
|
||||
/// @param start
|
||||
|
@ -152,8 +143,6 @@ void HDAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get disk cache path
|
||||
/// @return
|
||||
///
|
||||
|
@ -166,8 +155,6 @@ wxString HDAudioProvider::DiskCachePath() {
|
|||
return DecodeRelativePath(path,StandardPaths::DecodePath(_T("?user/")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get disk cache filename
|
||||
///
|
||||
wxString HDAudioProvider::DiskCacheName() {
|
||||
|
@ -180,17 +167,6 @@ wxString HDAudioProvider::DiskCacheName() {
|
|||
// File exists?
|
||||
wxString curStringTry = DiskCachePath() + wxString::Format(pattern.c_str(),i);
|
||||
if (!wxFile::Exists(curStringTry)) return curStringTry;
|
||||
|
||||
// Exists, see if it can be opened (disabled because wx doesn't seem to lock the files...)
|
||||
if (false) {
|
||||
wxFile test(curStringTry,wxFile::write);
|
||||
if (test.IsOpened()) {
|
||||
test.Close();
|
||||
return curStringTry;
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
}
|
||||
return _T("");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -47,8 +47,6 @@
|
|||
///
|
||||
/// DOCME
|
||||
class HDAudioProvider : public AudioProvider {
|
||||
private:
|
||||
|
||||
/// DOCME
|
||||
wxMutex diskmutex;
|
||||
|
||||
|
@ -71,9 +69,6 @@ public:
|
|||
HDAudioProvider(AudioProvider *source);
|
||||
~HDAudioProvider();
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
///
|
||||
bool AreSamplesNativeEndian() const { return samples_native_endian; }
|
||||
|
||||
void GetAudio(void *buf, int64_t start, int64_t count);
|
||||
|
|
|
@ -64,7 +64,6 @@
|
|||
PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
|
||||
file_handle = CreateFile(
|
||||
filename.c_str(),
|
||||
FILE_READ_DATA,
|
||||
|
@ -75,14 +74,13 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
|||
0);
|
||||
|
||||
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||
wxLogWarning(_T("PCM audio provider: Could not open audio file for reading (%d)"), GetLastError());
|
||||
throw "PCM audio provider: Could not open audio file for reading";
|
||||
throw agi::FileNotFoundError(filename);
|
||||
}
|
||||
|
||||
LARGE_INTEGER li_file_size = {0};
|
||||
if (!GetFileSizeEx(file_handle, &li_file_size)) {
|
||||
CloseHandle(file_handle);
|
||||
throw "PCM audio provider: Failed getting file size";
|
||||
throw AudioOpenError("Failed getting file size");
|
||||
}
|
||||
file_size = li_file_size.QuadPart;
|
||||
|
||||
|
@ -95,7 +93,7 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
|||
|
||||
if (file_mapping == 0) {
|
||||
CloseHandle(file_handle);
|
||||
throw "PCM audio provider: Failed creating file mapping";
|
||||
throw AudioOpenError("Failed creating file mapping");
|
||||
}
|
||||
|
||||
current_mapping = 0;
|
||||
|
@ -105,50 +103,41 @@ PCMAudioProvider::PCMAudioProvider(const wxString &filename)
|
|||
file_handle = open(filename.mb_str(*wxConvFileName), O_RDONLY);
|
||||
|
||||
if (file_handle == -1) {
|
||||
throw "PCM audio provider: Could not open audio file for reading";
|
||||
throw agi::FileNotFoundError(filename);
|
||||
}
|
||||
|
||||
struct stat filestats;
|
||||
memset(&filestats, 0, sizeof(filestats));
|
||||
if (fstat(file_handle, &filestats)) {
|
||||
close(file_handle);
|
||||
throw "PCM audio provider: Could not stat file to get size";
|
||||
throw AudioOpenError("Could not stat file to get size");
|
||||
}
|
||||
file_size = filestats.st_size;
|
||||
|
||||
current_mapping = 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
///
|
||||
PCMAudioProvider::~PCMAudioProvider()
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
|
||||
if (current_mapping) {
|
||||
UnmapViewOfFile(current_mapping);
|
||||
}
|
||||
|
||||
CloseHandle(file_mapping);
|
||||
CloseHandle(file_handle);
|
||||
|
||||
#else
|
||||
|
||||
if (current_mapping) {
|
||||
munmap(current_mapping, mapping_length);
|
||||
}
|
||||
|
||||
close(file_handle);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param range_start
|
||||
/// @param range_length
|
||||
|
@ -157,14 +146,12 @@ PCMAudioProvider::~PCMAudioProvider()
|
|||
char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t range_length)
|
||||
{
|
||||
if (range_start + range_length > file_size) {
|
||||
throw "PCM audio provider: Attempted to map beyond end of file";
|
||||
throw AudioDecodeError("Attempted to map beyond end of file");
|
||||
}
|
||||
|
||||
// Check whether the requested range is already visible
|
||||
if (!current_mapping || range_start < mapping_start || range_start+range_length > mapping_start+(int64_t)mapping_length) {
|
||||
|
||||
// It's not visible, change the current mapping
|
||||
|
||||
if (current_mapping) {
|
||||
#ifdef _WINDOWS
|
||||
UnmapViewOfFile(current_mapping);
|
||||
|
@ -187,8 +174,7 @@ char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t rang
|
|||
// Make sure to always make a mapping at least as large as the requested range
|
||||
if ((int64_t)mapping_length < range_length) {
|
||||
if (range_length > (int64_t)(~(size_t)0))
|
||||
throw "PCM audio provider: Requested range larger than max size_t, cannot create view of file";
|
||||
else
|
||||
throw AudioDecodeError("Requested range larger than max size_t, cannot create view of file");
|
||||
mapping_length = range_length;
|
||||
}
|
||||
// But also make sure we don't try to make a mapping larger than the file
|
||||
|
@ -211,9 +197,8 @@ char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t rang
|
|||
#endif
|
||||
|
||||
if (!current_mapping) {
|
||||
throw "PCM audio provider: Failed mapping a view of the file";
|
||||
throw AudioDecodeError("Failed mapping a view of the file");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
assert(current_mapping);
|
||||
|
@ -226,8 +211,6 @@ char * PCMAudioProvider::EnsureRangeAccessible(int64_t range_start, int64_t rang
|
|||
return ((char*)current_mapping) + rel_ofs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param buf
|
||||
/// @param start
|
||||
|
@ -256,9 +239,7 @@ void PCMAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
|||
buf = (char*)buf + samples_can_do * bytes_per_sample * channels;
|
||||
start += samples_can_do;
|
||||
count -= samples_can_do;
|
||||
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
|
@ -273,26 +254,17 @@ void PCMAudioProvider::GetAudio(void *buf, int64_t start, int64_t count)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// RIFF WAV PCM provider
|
||||
// Overview of RIFF WAV: <http://www.sonicspot.com/guide/wavefiles.html>
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class RiffWavPCMAudioProvider
|
||||
/// @brief DOCME
|
||||
/// @brief RIFF WAV PCM provider
|
||||
///
|
||||
/// DOCME
|
||||
/// Overview of RIFF WAV: <http://www.sonicspot.com/guide/wavefiles.html>
|
||||
class RiffWavPCMAudioProvider : public PCMAudioProvider {
|
||||
private:
|
||||
|
||||
/// DOCME
|
||||
struct ChunkHeader {
|
||||
|
||||
/// DOCME
|
||||
/// Always "RIFF"
|
||||
char type[4];
|
||||
|
||||
/// DOCME
|
||||
/// File size minus sizeof(ChunkHeader) (i.e. 8)
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
|
@ -302,29 +274,31 @@ private:
|
|||
/// DOCME
|
||||
ChunkHeader ch;
|
||||
|
||||
/// DOCME
|
||||
/// Always "WAVE"
|
||||
char format[4];
|
||||
};
|
||||
|
||||
/// DOCME
|
||||
struct fmtChunk {
|
||||
|
||||
/// DOCME
|
||||
uint16_t compression; // compression format used -- 0x0001 = PCM
|
||||
/// compression format used
|
||||
/// We support only PCM (0x1)
|
||||
uint16_t compression;
|
||||
|
||||
/// DOCME
|
||||
/// Number of channels
|
||||
uint16_t channels;
|
||||
|
||||
/// DOCME
|
||||
/// Samples per second
|
||||
uint32_t samplerate;
|
||||
|
||||
/// DOCME
|
||||
uint32_t avg_bytes_sec; // can't always be trusted
|
||||
/// Bytes per second
|
||||
/// can't always be trusted
|
||||
uint32_t avg_bytes_sec;
|
||||
|
||||
/// DOCME
|
||||
/// Bytes per sample
|
||||
uint16_t block_align;
|
||||
|
||||
/// DOCME
|
||||
/// Bits per sample that are actually used; rest should be ignored
|
||||
uint16_t significant_bits_sample;
|
||||
// Here was supposed to be some more fields but we don't need them
|
||||
// and just skipping by the size of the struct wouldn't be safe
|
||||
|
@ -359,16 +333,14 @@ public:
|
|||
filename = _filename;
|
||||
|
||||
// Read header
|
||||
// This should throw an exception if the mapping fails
|
||||
void *filestart = EnsureRangeAccessible(0, sizeof(RIFFChunk));
|
||||
assert(filestart);
|
||||
RIFFChunk &header = *(RIFFChunk*)filestart;
|
||||
|
||||
// Check magic values
|
||||
if (!CheckFourcc(header.ch.type, "RIFF"))
|
||||
throw "RIFF PCM WAV audio provider: File is not a RIFF file";
|
||||
throw AudioOpenError("File is not a RIFF file");
|
||||
if (!CheckFourcc(header.format, "WAVE"))
|
||||
throw "RIFF PCM WAV audio provider: File is not a RIFF WAV file";
|
||||
throw AudioOpenError("File is not a RIFF WAV file");
|
||||
|
||||
// Count how much more data we can have in the entire file
|
||||
// The first 4 bytes are already eaten by the header.format field
|
||||
|
@ -391,12 +363,13 @@ public:
|
|||
filepos += sizeof(ch);
|
||||
|
||||
if (CheckFourcc(ch.type, "fmt ")) {
|
||||
if (got_fmt_header) throw "RIFF PCM WAV audio provider: Invalid file, multiple 'fmt ' chunks";
|
||||
if (got_fmt_header) throw AudioOpenError("Invalid file, multiple 'fmt ' chunks");
|
||||
got_fmt_header = true;
|
||||
|
||||
fmtChunk &fmt = *(fmtChunk*)EnsureRangeAccessible(filepos, sizeof(fmtChunk));
|
||||
|
||||
if (Endian::LittleToMachine(fmt.compression) != 1) throw "RIFF PCM WAV audio provider: Can't use file, not PCM encoding";
|
||||
if (Endian::LittleToMachine(fmt.compression) != 1)
|
||||
throw AudioOpenError("Can't use file, not PCM encoding");
|
||||
|
||||
// Set stuff inherited from the AudioProvider class
|
||||
sample_rate = Endian::LittleToMachine(fmt.samplerate);
|
||||
|
@ -408,7 +381,7 @@ public:
|
|||
// This won't pick up 'data' chunks inside 'wavl' chunks
|
||||
// since the 'wavl' chunks wrap those.
|
||||
|
||||
if (!got_fmt_header) throw "RIFF PCM WAV audio provider: Found 'data' chunk before 'fmt ' chunk, file is invalid.";
|
||||
if (!got_fmt_header) throw AudioOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.");
|
||||
|
||||
int64_t samples = Endian::LittleToMachine(ch.size) / bytes_per_sample;
|
||||
int64_t frames = samples / channels;
|
||||
|
@ -431,8 +404,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -446,12 +417,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Sony Wave64 audio provider
|
||||
// Specs obtained at: <http://www.vcs.de/fileadmin/user_upload/MBS/PDF/Whitepaper/Informations_about_Sony_Wave64.pdf>
|
||||
|
||||
|
||||
/// DOCME
|
||||
static const uint8_t w64GuidRIFF[16] = {
|
||||
// {66666972-912E-11CF-A5D6-28DB04C10000}
|
||||
|
@ -482,43 +447,25 @@ static const uint8_t w64Guiddata[16] = {
|
|||
|
||||
/// DOCME
|
||||
/// @class Wave64AudioProvider
|
||||
/// @brief DOCME
|
||||
/// @brief Sony Wave64 audio provider
|
||||
///
|
||||
/// DOCME
|
||||
/// http://www.vcs.de/fileadmin/user_upload/MBS/PDF/Whitepaper/Informations_about_Sony_Wave64.pdf
|
||||
class Wave64AudioProvider : public PCMAudioProvider {
|
||||
private:
|
||||
// Here's some copy-paste from the FFmpegSource2 code
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx
|
||||
struct WaveFormatEx {
|
||||
|
||||
/// DOCME
|
||||
uint16_t wFormatTag;
|
||||
|
||||
/// DOCME
|
||||
uint16_t nChannels;
|
||||
|
||||
/// DOCME
|
||||
uint32_t nSamplesPerSec;
|
||||
|
||||
/// DOCME
|
||||
uint32_t nAvgBytesPerSec;
|
||||
|
||||
/// DOCME
|
||||
uint16_t nBlockAlign;
|
||||
|
||||
/// DOCME
|
||||
uint16_t wBitsPerSample;
|
||||
|
||||
/// DOCME
|
||||
uint16_t cbSize;
|
||||
};
|
||||
|
||||
|
||||
/// DOCME
|
||||
struct RiffChunk {
|
||||
|
||||
/// DOCME
|
||||
uint8_t riff_guid[16];
|
||||
|
||||
|
@ -532,7 +479,6 @@ private:
|
|||
|
||||
/// DOCME
|
||||
struct FormatChunk {
|
||||
|
||||
/// DOCME
|
||||
uint8_t chunk_guid[16];
|
||||
|
||||
|
@ -549,7 +495,6 @@ private:
|
|||
|
||||
/// DOCME
|
||||
struct DataChunk {
|
||||
|
||||
/// DOCME
|
||||
uint8_t chunk_guid[16];
|
||||
|
||||
|
@ -557,7 +502,6 @@ private:
|
|||
uint64_t chunk_size;
|
||||
};
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param guid1
|
||||
/// @param guid2
|
||||
|
@ -581,7 +525,7 @@ public:
|
|||
int64_t smallest_possible_file = sizeof(RiffChunk) + sizeof(FormatChunk) + sizeof(DataChunk);
|
||||
|
||||
if (file_size < smallest_possible_file)
|
||||
throw "Wave64 audio provider: File is too small to be a Wave64 file";
|
||||
throw AudioOpenError("File is too small to be a Wave64 file");
|
||||
|
||||
// Read header
|
||||
// This should throw an exception if the mapping fails
|
||||
|
@ -591,9 +535,9 @@ public:
|
|||
|
||||
// Check magic values
|
||||
if (!CheckGuid(header.riff_guid, w64GuidRIFF))
|
||||
throw "Wave64 audio provider: File is not a Wave64 RIFF file";
|
||||
throw AudioOpenError("File is not a Wave64 RIFF file");
|
||||
if (!CheckGuid(header.format_guid, w64GuidWAVE))
|
||||
throw "Wave64 audio provider: File is not a Wave64 WAVE file";
|
||||
throw AudioOpenError("File is not a Wave64 WAVE file");
|
||||
|
||||
// Count how much more data we can have in the entire file
|
||||
uint64_t data_left = Endian::LittleToMachine(header.file_size) - sizeof(RiffChunk);
|
||||
|
@ -613,25 +557,24 @@ public:
|
|||
|
||||
if (CheckGuid(chunk_guid, w64Guidfmt)) {
|
||||
if (got_fmt_header)
|
||||
throw "Wave64 audio provider: Bad file, found more than one 'fmt' chunk";
|
||||
throw AudioOpenError("Bad file, found more than one 'fmt' chunk");
|
||||
|
||||
FormatChunk &fmt = *(FormatChunk*)EnsureRangeAccessible(filepos, sizeof(FormatChunk));
|
||||
got_fmt_header = true;
|
||||
|
||||
if (Endian::LittleToMachine(fmt.format.wFormatTag) == 3)
|
||||
throw "Wave64 audio provider: File is IEEE 32 bit float format which isn't supported. Bug the developers if this matters.";
|
||||
throw AudioOpenError("File is IEEE 32 bit float format which isn't supported. Bug the developers if this matters.");
|
||||
if (Endian::LittleToMachine(fmt.format.wFormatTag) != 1)
|
||||
throw "Wave64 audio provider: Can't use file, not PCM encoding";
|
||||
throw AudioOpenError("Can't use file, not PCM encoding");
|
||||
|
||||
// Set stuff inherited from the AudioProvider class
|
||||
sample_rate = Endian::LittleToMachine(fmt.format.nSamplesPerSec);
|
||||
channels = Endian::LittleToMachine(fmt.format.nChannels);
|
||||
bytes_per_sample = (Endian::LittleToMachine(fmt.format.wBitsPerSample) + 7) / 8; // round up to nearest whole byte
|
||||
}
|
||||
|
||||
else if (CheckGuid(chunk_guid, w64Guiddata)) {
|
||||
if (!got_fmt_header)
|
||||
throw "Wave64 audio provider: Found 'data' chunk before 'fmt ' chunk, file is invalid.";
|
||||
throw AudioOpenError("Found 'data' chunk before 'fmt ' chunk, file is invalid.");
|
||||
|
||||
int64_t samples = chunk_size / bytes_per_sample;
|
||||
int64_t frames = samples / channels;
|
||||
|
@ -652,8 +595,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -667,38 +608,23 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param filename
|
||||
///
|
||||
AudioProvider *CreatePCMAudioProvider(const wxString &filename)
|
||||
{
|
||||
AudioProvider *provider = 0;
|
||||
|
||||
// Try Microsoft/IBM RIFF WAV
|
||||
std::string msg;
|
||||
try {
|
||||
provider = new RiffWavPCMAudioProvider(filename);
|
||||
// don't bother trying with anything else if this works
|
||||
return provider;
|
||||
return new RiffWavPCMAudioProvider(filename);
|
||||
}
|
||||
catch (const char *msg) {
|
||||
LOG_E("audio/provider/pcm") << "Creating PCM WAV reader failed with message: '" << msg << "' Trying other providers";
|
||||
provider = 0;
|
||||
catch (AudioOpenError const& err) {
|
||||
msg = "RIFF PCM WAV audio provider: " + err.GetMessage();
|
||||
}
|
||||
|
||||
// Try Sony Wave64
|
||||
try {
|
||||
provider = new Wave64AudioProvider(filename);
|
||||
return provider;
|
||||
return new Wave64AudioProvider(filename);
|
||||
}
|
||||
catch (const char *msg) {
|
||||
LOG_E("audio/provider/pcm") << "Creating Wave64 reader failed with message: '" << msg << "' Trying other providers";
|
||||
provider = 0;
|
||||
catch (AudioOpenError const& err) {
|
||||
msg += "\nWave64 audio provider: " + err.GetMessage();
|
||||
throw AudioOpenError(msg);
|
||||
}
|
||||
|
||||
// no providers could be created
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup audio_input
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#include "audio_provider_ram.h"
|
||||
|
@ -52,12 +49,11 @@
|
|||
/// DOCME
|
||||
#define CacheBlockSize ((1 << CacheBits))
|
||||
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param source
|
||||
///
|
||||
RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
||||
RAMAudioProvider::RAMAudioProvider(AudioProvider *src) {
|
||||
std::auto_ptr<AudioProvider> source(src);
|
||||
// Init
|
||||
blockcache = NULL;
|
||||
blockcount = 0;
|
||||
|
@ -79,7 +75,7 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
|||
}
|
||||
catch (...) {
|
||||
Clear();
|
||||
throw wxString(_T("Couldn't open audio, not enough ram available."));
|
||||
throw AudioOpenError("Couldn't open audio, not enough ram available.");
|
||||
}
|
||||
|
||||
// Copy parameters
|
||||
|
@ -98,7 +94,6 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
|||
// Read cache
|
||||
int readsize = CacheBlockSize / source->GetBytesPerSample();
|
||||
for (int i=0;i<blockcount && !canceled; i++) {
|
||||
//tempclip->GetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (num_samples - i*readsize) : readsize,env);
|
||||
source->GetAudio((char*)blockcache[i],i*readsize, i == blockcount-1 ? (source->GetNumSamples() - i*readsize) : readsize);
|
||||
progress->SetProgress(i,blockcount-1);
|
||||
}
|
||||
|
@ -107,20 +102,16 @@ RAMAudioProvider::RAMAudioProvider(AudioProvider *source) {
|
|||
progress->Destroy();
|
||||
if (canceled) {
|
||||
Clear();
|
||||
throw wxString(_T("Audio loading cancelled by user"));
|
||||
throw agi::UserCancelException("Audio loading cancelled by user");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
RAMAudioProvider::~RAMAudioProvider() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Clear
|
||||
///
|
||||
void RAMAudioProvider::Clear() {
|
||||
|
@ -135,8 +126,6 @@ void RAMAudioProvider::Clear() {
|
|||
blockcount = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get audio
|
||||
/// @param buf
|
||||
/// @param start
|
||||
|
@ -185,5 +174,3 @@ void RAMAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ public:
|
|||
// Start sample number of the next line calculated
|
||||
// line_length is half of the number of samples used to calculate a line, since half of the output from
|
||||
// a Fourier transform of real data is redundant, and not interesting for the purpose of creating
|
||||
// a frequenmcy/power spectrum.
|
||||
// a frequency/power spectrum.
|
||||
int64_t sample = start * line_length*2 + overlap*overlap_offset;
|
||||
|
||||
long len = length;
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
/// @ingroup scripting
|
||||
///
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef WITH_AUTOMATION
|
||||
|
@ -47,15 +46,11 @@
|
|||
|
||||
#include <wx/button.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/gauge.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/thread.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#endif
|
||||
|
@ -73,12 +68,8 @@
|
|||
#include "standard_paths.h"
|
||||
#include "string_codec.h"
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
namespace Automation4 {
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param style
|
||||
/// @param text
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup scripting
|
||||
///
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <wx/event.h>
|
||||
#include <wx/thread.h>
|
||||
|
@ -47,7 +44,6 @@
|
|||
|
||||
#ifdef __WINDOWS__
|
||||
#include "../../contrib/lua51/src/lua.h"
|
||||
#include "../../contrib/lua51/src/lauxlib.h"
|
||||
#else
|
||||
#include <lua.hpp>
|
||||
#endif
|
||||
|
@ -55,11 +51,8 @@
|
|||
class wxWindow;
|
||||
namespace agi { namespace vfr { class Framerate; } }
|
||||
|
||||
|
||||
/// DOCME
|
||||
namespace Automation4 {
|
||||
|
||||
|
||||
/// @class LuaAssFile
|
||||
/// @brief Object wrapping an AssFile object for modification through Lua
|
||||
class LuaAssFile {
|
||||
|
|
|
@ -46,6 +46,7 @@ HINSTANCE AviSynthWrapper::hLib = NULL;
|
|||
IScriptEnvironment *AviSynthWrapper::env = NULL;
|
||||
wxMutex AviSynthWrapper::AviSynthMutex;
|
||||
|
||||
|
||||
/// @brief AviSynth constructor
|
||||
///
|
||||
AviSynthWrapper::AviSynthWrapper() {
|
||||
|
@ -96,3 +97,4 @@ IScriptEnvironment *AviSynthWrapper::GetEnv() {
|
|||
return env;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <libaegisub/colour.h>
|
||||
|
||||
#define STD_STR(x) std::string(x.utf8_str())
|
||||
#define STD_STR(x) std::string((x).utf8_str())
|
||||
|
||||
inline wxColour lagi_wxColour(const agi::Colour &colour) { return wxColour(colour); }
|
||||
inline wxString lagi_wxString(const std::string &str) { return wxString(str.c_str(), wxConvUTF8); }
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
#ifdef WITH_FFMPEGSOURCE
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#ifndef AGI_PRE
|
||||
#include <map>
|
||||
#include <wx/dir.h>
|
||||
|
@ -98,7 +96,8 @@ FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, const wxStri
|
|||
// set up progress dialog callback
|
||||
IndexingProgressDialog Progress;
|
||||
Progress.IndexingCanceled = false;
|
||||
Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame, _("Indexing"), &Progress.IndexingCanceled,
|
||||
Progress.ProgressDialog = new DialogProgress(AegisubApp::Get()->frame,
|
||||
_("Indexing"), &Progress.IndexingCanceled,
|
||||
_("Reading timecodes and frame/sample data"), 0, 1);
|
||||
Progress.ProgressDialog->Show();
|
||||
Progress.ProgressDialog->SetProgress(0,1);
|
||||
|
@ -106,12 +105,14 @@ FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, const wxStri
|
|||
// index all audio tracks
|
||||
FFMS_Index *Index = FFMS_DoIndexing(Indexer, Trackmask, FFMS_TRACKMASK_NONE, NULL, NULL, IndexEH,
|
||||
FFmpegSourceProvider::UpdateIndexingProgress, &Progress, &ErrInfo);
|
||||
if (Index == NULL) {
|
||||
Progress.ProgressDialog->Destroy();
|
||||
if (Progress.IndexingCanceled) {
|
||||
throw agi::UserCancelException("indexing cancelled by user");
|
||||
}
|
||||
if (Index == NULL) {
|
||||
MsgString.Append(_T("Failed to index: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
||||
throw MsgString;
|
||||
}
|
||||
Progress.ProgressDialog->Destroy();
|
||||
|
||||
// write index to disk for later use
|
||||
// ignore write errors for now
|
||||
|
@ -125,8 +126,6 @@ FFMS_Index *FFmpegSourceProvider::DoIndexing(FFMS_Indexer *Indexer, const wxStri
|
|||
return Index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Finds all tracks of the given type and return their track numbers and respective codec names
|
||||
/// @param Indexer The indexer object representing the source file
|
||||
/// @param Type The track type to look for
|
||||
|
@ -141,12 +140,9 @@ std::map<int,wxString> FFmpegSourceProvider::GetTracksOfType(FFMS_Indexer *Index
|
|||
TrackList.insert(std::pair<int,wxString>(i, CodecName));
|
||||
}
|
||||
}
|
||||
|
||||
return TrackList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Ask user for which track he wants to load
|
||||
/// @param TrackList A std::map with the track numbers as keys and codec names as values
|
||||
/// @param Type The track type to ask about
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
|
||||
#ifdef WITH_FFMPEGSOURCE
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#ifndef AGI_PRE
|
||||
#include <map>
|
||||
|
||||
|
@ -48,15 +46,12 @@
|
|||
#include <ffms.h>
|
||||
|
||||
#include "dialog_progress.h"
|
||||
#include "include/aegisub/aegisub.h"
|
||||
|
||||
|
||||
/// Index all tracks
|
||||
#define FFMS_TRACKMASK_ALL -1
|
||||
/// Index no tracks
|
||||
#define FFMS_TRACKMASK_NONE 0
|
||||
|
||||
|
||||
/// @class FFmpegSourceProvider
|
||||
/// @brief Base class for FFMS2 source providers; contains common functions etc
|
||||
class FFmpegSourceProvider {
|
||||
|
@ -97,8 +92,6 @@ public:
|
|||
virtual ~FFmpegSourceProvider() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// @class FFmpegSourceCacheCleaner
|
||||
/// @brief Implements index cache cleaning functionality for the FFMS2 providers
|
||||
class FFmpegSourceCacheCleaner : public wxThread {
|
||||
|
@ -112,8 +105,5 @@ public:
|
|||
wxThread::ExitCode Entry();
|
||||
};
|
||||
|
||||
|
||||
#endif /* WITH_FFMPEGSOURCE */
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -673,7 +673,7 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
|||
}
|
||||
|
||||
// Setup
|
||||
bool isFile = (filename != _T(""));
|
||||
bool isFile = !filename.empty();
|
||||
bool isBinary = false;
|
||||
|
||||
// Load
|
||||
|
@ -681,7 +681,9 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
|||
// File exists?
|
||||
if (isFile) {
|
||||
wxFileName fileCheck(filename);
|
||||
if (!fileCheck.FileExists()) throw _T("Selected file does not exist.");
|
||||
if (!fileCheck.FileExists()) {
|
||||
throw agi::FileNotFoundError(STD_STR(filename));
|
||||
}
|
||||
|
||||
// Make sure that file isn't actually a timecode file
|
||||
try {
|
||||
|
@ -697,8 +699,8 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
|||
}
|
||||
}
|
||||
catch (...) {
|
||||
// if trying to load the file as timecodes fails it's fairly safe to assume that
|
||||
// it is in fact not a timecode file
|
||||
// if trying to load the file as timecodes fails it's fairly
|
||||
// safe to assume that it is in fact not a timecode file
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,6 +722,11 @@ void FrameMain::LoadSubtitles (wxString filename,wxString charset) {
|
|||
StandardPaths::SetPathValue(_T("?script"),_T(""));
|
||||
}
|
||||
}
|
||||
catch (agi::FileNotFoundError const&) {
|
||||
wxMessageBox(filename + L" not found.", L"Error", wxOK | wxICON_ERROR, NULL);
|
||||
config::mru->Remove("Subtitle", STD_STR(filename));
|
||||
return;
|
||||
}
|
||||
catch (const wchar_t *err) {
|
||||
wxMessageBox(wxString(err), _T("Error"), wxOK | wxICON_ERROR, NULL);
|
||||
return;
|
||||
|
|
|
@ -34,15 +34,11 @@
|
|||
/// @ingroup main_ui
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
#include <fstream>
|
||||
|
||||
#include <wx/accel.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#endif
|
||||
|
@ -51,7 +47,6 @@
|
|||
#include "text_file_reader.h"
|
||||
#include "text_file_writer.h"
|
||||
|
||||
|
||||
/// @brief Constructors HotkeyType //////////////////////////////////
|
||||
///
|
||||
HotkeyType::HotkeyType() {
|
||||
|
@ -59,7 +54,6 @@ HotkeyType::HotkeyType() {
|
|||
keycode = 0;
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param text
|
||||
/// @param name
|
||||
|
@ -69,8 +63,6 @@ HotkeyType::HotkeyType(wxString text,wxString name) {
|
|||
origName = name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get string of hotkey
|
||||
/// @return
|
||||
///
|
||||
|
@ -88,8 +80,6 @@ wxString HotkeyType::GetText() const {
|
|||
return text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Parse text into hotkey
|
||||
/// @param text
|
||||
///
|
||||
|
@ -150,8 +140,6 @@ void HotkeyType::Parse(wxString text) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
std::map<int,wxString> HotkeyType::keyName;
|
||||
|
||||
|
@ -172,8 +160,6 @@ wxString HotkeyType::GetKeyName(int keycode) {
|
|||
else return wxString::Format(_T("[%i]"),keycode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Fill map
|
||||
/// @return
|
||||
///
|
||||
|
@ -234,29 +220,21 @@ void HotkeyType::FillMap() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
HotkeyManager Hotkeys;
|
||||
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
HotkeyManager::HotkeyManager() {
|
||||
modified = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
HotkeyManager::~HotkeyManager() {
|
||||
key.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Save
|
||||
/// @return
|
||||
///
|
||||
|
@ -278,8 +256,6 @@ void HotkeyManager::Save() {
|
|||
modified = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Load
|
||||
/// @return
|
||||
///
|
||||
|
@ -353,14 +329,11 @@ void HotkeyManager::Load() {
|
|||
Save();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set all hotkeys to the default values
|
||||
///
|
||||
void HotkeyManager::LoadDefaults() {
|
||||
modified = true;
|
||||
|
||||
|
||||
/// @note () is used here instead of _T(). This is done so the strings can be extracted.
|
||||
/// However, since this function is called before locale is set, it won't ever be translated.
|
||||
/// Keep this in mind: THESE CANNOT BE TRANSLATED HERE!
|
||||
|
@ -503,8 +476,6 @@ void HotkeyManager::LoadDefaults() {
|
|||
SetHotkey(_("Visual Tool Vector Clip"), _T("J"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set hotkey
|
||||
/// @param function
|
||||
/// @param hotkey
|
||||
|
@ -514,7 +485,6 @@ void HotkeyManager::SetHotkey(wxString function,HotkeyType hotkey) {
|
|||
modified = true;
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param function
|
||||
/// @param hotkey
|
||||
|
@ -524,8 +494,6 @@ void HotkeyManager::SetHotkey(wxString function,wxString hotkey) {
|
|||
modified = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set file
|
||||
/// @param file
|
||||
///
|
||||
|
@ -533,8 +501,6 @@ void HotkeyManager::SetFile(wxString file) {
|
|||
filename = file;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get hotkey as text
|
||||
/// @param function
|
||||
/// @return
|
||||
|
@ -547,8 +513,6 @@ const wxString HotkeyManager::GetText(wxString function) const {
|
|||
else throw _T("Hotkey not defined");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get hotkey as accelerator entry
|
||||
/// @param function
|
||||
/// @param id
|
||||
|
@ -565,8 +529,6 @@ wxAcceleratorEntry HotkeyManager::GetAccelerator(wxString function,int id) const
|
|||
else throw _T("Hotkey not defined");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set last key pressed
|
||||
/// @param keypress
|
||||
/// @param ctrl
|
||||
|
@ -581,8 +543,6 @@ void HotkeyManager::SetPressed(int keypress,bool ctrl,bool alt,bool shift) {
|
|||
if (shift) lastMod |= wxACCEL_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Is pressed?
|
||||
/// @param function
|
||||
/// @return
|
||||
|
@ -596,8 +556,6 @@ bool HotkeyManager::IsPressed(wxString function) const {
|
|||
else throw _T("Hotkey not defined");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Search for a hotkey
|
||||
/// @param keycode
|
||||
/// @param mod
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <wx/string.h>
|
||||
#endif
|
||||
|
||||
#include <libaegisub/exception.h>
|
||||
#include "factory_manager.h"
|
||||
|
||||
/// @class AudioProvider
|
||||
|
@ -88,6 +89,9 @@ public:
|
|||
virtual bool AreSamplesNativeEndian() const = 0;
|
||||
|
||||
void GetWaveForm(int *min,int *peak,int64_t start,int w,int h,int samples,float scale);
|
||||
|
||||
/// @brief Does this provider benefit from external caching?
|
||||
virtual bool NeedsCache() const { return false; }
|
||||
};
|
||||
|
||||
/// DOCME
|
||||
|
@ -100,3 +104,9 @@ public:
|
|||
static void RegisterProviders();
|
||||
static AudioProvider *GetProvider(wxString filename, int cache=-1);
|
||||
};
|
||||
|
||||
DEFINE_BASE_EXCEPTION_NOINNER(AudioProviderError, agi::Exception);
|
||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(AudioOpenError, AudioProviderError, "audio/open/failed");
|
||||
|
||||
/// Error of some sort occurred while decoding a frame
|
||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(AudioDecodeError, AudioProviderError, "audio/error");
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "video_frame.h"
|
||||
#include <libaegisub/exception.h>
|
||||
#include <libaegisub/vfr.h>
|
||||
|
||||
/// @class VideoProvider
|
||||
|
@ -69,3 +70,12 @@ public:
|
|||
/// @return Returns true if caching is desired, false otherwise.
|
||||
virtual bool WantsCaching() const { return false; }
|
||||
};
|
||||
|
||||
DEFINE_BASE_EXCEPTION_NOINNER(VideoProviderError, agi::Exception);
|
||||
/// File could be opened, but is not a supported format
|
||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoNotSupported, VideoProviderError, "video/open/notsupported");
|
||||
/// File appears to be a supported format, but could not be opened
|
||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoOpenError, VideoProviderError, "video/open/failed");
|
||||
|
||||
/// Error of some sort occurred while decoding a frame
|
||||
DEFINE_SIMPLE_EXCEPTION_NOINNER(VideoDecodeError, VideoProviderError, "video/error");
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
|
||||
#ifndef AGI_PRE
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
@ -54,33 +53,24 @@
|
|||
#include <libaegisub/vfr.h>
|
||||
#include "mkv_wrap.h"
|
||||
|
||||
|
||||
/// DOCME
|
||||
MatroskaWrapper MatroskaWrapper::wrapper;
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
#define CACHESIZE 65536
|
||||
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
MatroskaWrapper::MatroskaWrapper() {
|
||||
file = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
MatroskaWrapper::~MatroskaWrapper() {
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Open file
|
||||
/// @param filename
|
||||
/// @param parse
|
||||
|
@ -112,8 +102,6 @@ void MatroskaWrapper::Open(wxString filename,bool parse) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Close file
|
||||
/// @return
|
||||
///
|
||||
|
@ -127,8 +115,6 @@ void MatroskaWrapper::Close() {
|
|||
timecodes.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Return keyframes
|
||||
/// @return
|
||||
///
|
||||
|
@ -136,8 +122,6 @@ std::vector<int> MatroskaWrapper::GetKeyFrames() {
|
|||
return keyFrames;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Comparison operator
|
||||
/// @param t1
|
||||
/// @param t2
|
||||
|
@ -147,8 +131,6 @@ bool operator < (MkvFrame &t1, MkvFrame &t2) {
|
|||
return t1.time < t2.time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Actually parse
|
||||
///
|
||||
void MatroskaWrapper::Parse() {
|
||||
|
@ -200,7 +182,7 @@ void MatroskaWrapper::Parse() {
|
|||
// Cancelled?
|
||||
if (canceled) {
|
||||
Close();
|
||||
throw _T("Canceled");
|
||||
throw agi::UserCancelException("Canceled");
|
||||
}
|
||||
|
||||
// Identical to (frameN % 2048) == 0,
|
||||
|
@ -257,7 +239,6 @@ void MatroskaWrapper::Parse() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static int mkv_round(double num) {
|
||||
return (int)(num + .5);
|
||||
}
|
||||
|
@ -275,8 +256,6 @@ void MatroskaWrapper::SetToTimecodes(agi::vfr::Framerate &target) {
|
|||
target = agi::vfr::Framerate(times);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get subtitles
|
||||
/// @param target
|
||||
///
|
||||
|
@ -330,7 +309,7 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
|
|||
if (choice == -1) {
|
||||
target->LoadDefault(true);
|
||||
Close();
|
||||
throw _T("Canceled.");
|
||||
throw agi::UserCancelException("cancelled");
|
||||
}
|
||||
trackToRead = tracksFound[choice];
|
||||
}
|
||||
|
@ -398,7 +377,7 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
|
|||
if (canceled) {
|
||||
target->LoadDefault(true);
|
||||
Close();
|
||||
throw _T("Canceled");
|
||||
throw agi::UserCancelException("cancelled");
|
||||
}
|
||||
|
||||
// Read to temp
|
||||
|
@ -525,7 +504,6 @@ bool MatroskaWrapper::HasSubtitles(wxString const& filename) {
|
|||
#define std_ftell ftello
|
||||
#endif
|
||||
|
||||
|
||||
/// @brief STDIO class
|
||||
/// @param _st
|
||||
/// @param pos
|
||||
|
@ -577,7 +555,6 @@ longlong StdIoScan(InputStream *_st, ulonglong start, unsigned signature) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/// @brief This is used to limit readahead.
|
||||
/// @param _st
|
||||
/// @return Cache size
|
||||
|
@ -586,7 +563,6 @@ unsigned StdIoGetCacheSize(InputStream *_st) {
|
|||
return CACHESIZE;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Get last error message
|
||||
/// @param _st
|
||||
/// @return Last error message
|
||||
|
@ -596,7 +572,6 @@ const char *StdIoGetLastError(InputStream *_st) {
|
|||
return strerror(st->error);
|
||||
}
|
||||
|
||||
|
||||
/// @brief Memory allocation, this is done via stdlib
|
||||
/// @param _st
|
||||
/// @param size
|
||||
|
@ -606,7 +581,6 @@ void *StdIoMalloc(InputStream *_st, size_t size) {
|
|||
return malloc(size);
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param _st
|
||||
/// @param mem
|
||||
|
@ -617,7 +591,6 @@ void *StdIoRealloc(InputStream *_st, void *mem, size_t size) {
|
|||
return realloc(mem,size);
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param _st
|
||||
/// @param mem
|
||||
|
@ -626,7 +599,6 @@ void StdIoFree(InputStream *_st, void *mem) {
|
|||
free(mem);
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param _st
|
||||
/// @param cur
|
||||
|
@ -637,7 +609,6 @@ int StdIoProgress(InputStream *_st, ulonglong cur, ulonglong max) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param _st
|
||||
/// @return
|
||||
|
@ -652,7 +623,6 @@ longlong StdIoGetFileSize(InputStream *_st) {
|
|||
return epos;
|
||||
}
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @param filename
|
||||
///
|
||||
|
@ -673,4 +643,3 @@ MkvStdIO::MkvStdIO(wxString filename) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -64,8 +64,6 @@ public:
|
|||
int error;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class MkvFrame
|
||||
/// @brief DOCME
|
||||
|
@ -83,7 +81,6 @@ public:
|
|||
/// DOCME
|
||||
int64_t filePos;
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
///
|
||||
MkvFrame() {
|
||||
|
@ -107,7 +104,6 @@ public:
|
|||
bool operator < (MkvFrame &t1, MkvFrame &t2);
|
||||
|
||||
|
||||
|
||||
/// DOCME
|
||||
/// @class MatroskaWrapper
|
||||
/// @brief DOCME
|
||||
|
@ -142,7 +138,6 @@ public:
|
|||
MatroskaWrapper();
|
||||
~MatroskaWrapper();
|
||||
|
||||
|
||||
/// @brief DOCME
|
||||
/// @return
|
||||
///
|
||||
|
@ -166,9 +161,6 @@ public:
|
|||
void GetSubtitles(AssFile *target);
|
||||
static bool HasSubtitles(wxString const& filename);
|
||||
|
||||
|
||||
/// DOCME
|
||||
static MatroskaWrapper wrapper;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,12 +34,8 @@
|
|||
/// @ingroup spelling
|
||||
///
|
||||
|
||||
|
||||
///////////
|
||||
// Headers
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#ifdef WITH_HUNSPELL
|
||||
|
||||
#ifndef AGI_PRE
|
||||
|
@ -51,7 +47,6 @@
|
|||
#endif
|
||||
|
||||
#include <libaegisub/log.h>
|
||||
#include <hunspell/hunspell.hxx>
|
||||
|
||||
#include "charset_conv.h"
|
||||
#include "compat.h"
|
||||
|
@ -62,7 +57,6 @@
|
|||
#include "text_file_writer.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
HunspellSpellChecker::HunspellSpellChecker() {
|
||||
hunspell = NULL;
|
||||
|
@ -71,15 +65,11 @@ HunspellSpellChecker::HunspellSpellChecker() {
|
|||
SetLanguage(lagi_wxString(OPT_GET("Tool/Spell Checker/Language")->GetString()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
HunspellSpellChecker::~HunspellSpellChecker() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Reset spelling library
|
||||
void HunspellSpellChecker::Reset() {
|
||||
delete hunspell;
|
||||
|
@ -92,8 +82,6 @@ void HunspellSpellChecker::Reset() {
|
|||
dicpath.Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Can add to dictionary?
|
||||
/// @param word Word to check.
|
||||
/// @return Whether word can be added or not.
|
||||
|
@ -109,8 +97,6 @@ bool HunspellSpellChecker::CanAddWord(wxString word) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Add word to dictionary
|
||||
/// @param word Word to add.
|
||||
///
|
||||
|
@ -171,8 +157,6 @@ void HunspellSpellChecker::AddWord(wxString word) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Check if the word is valid.
|
||||
/// @param word Word to check
|
||||
/// @return Whether word is valid or not.
|
||||
|
@ -187,8 +171,6 @@ bool HunspellSpellChecker::CheckWord(wxString word) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get suggestions for word.
|
||||
/// @param word Word to get suggestions for
|
||||
/// @return List of suggestions
|
||||
|
@ -217,8 +199,6 @@ wxArrayString HunspellSpellChecker::GetSuggestions(wxString word) {
|
|||
return suggestions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Get list of available dictionaries.
|
||||
/// @return List of available dictionaries
|
||||
///
|
||||
|
@ -252,8 +232,6 @@ wxArrayString HunspellSpellChecker::GetLanguageList() {
|
|||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Set language.
|
||||
/// @param language Language to set
|
||||
///
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "subtitles_provider_csri.h"
|
||||
#include "text_file_writer.h"
|
||||
#include "video_context.h"
|
||||
#include "video_frame.h"
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param type
|
||||
|
|
|
@ -41,10 +41,7 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <wx/string.h>
|
||||
#endif
|
||||
|
||||
#include <libaegisub/io.h>
|
||||
|
|
|
@ -67,8 +67,7 @@ AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time,
|
|||
try {
|
||||
frame->CopyFrom(videoProvider->GetFrame(frameNum));
|
||||
}
|
||||
catch (const wchar_t *err) { throw VideoProviderErrorEvent(err); }
|
||||
catch (wxString const& err) { throw VideoProviderErrorEvent(err); }
|
||||
catch (VideoProviderError const& err) { throw VideoProviderErrorEvent(err); }
|
||||
}
|
||||
|
||||
// This deliberately results in a call to LoadSubtitles while a render
|
||||
|
@ -107,7 +106,6 @@ AegiVideoFrame const& ThreadedFrameSource::ProcFrame(int frameNum, double time,
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (const wchar_t *err) { throw SubtitlesProviderErrorEvent(err); }
|
||||
catch (wxString const& err) { throw SubtitlesProviderErrorEvent(err); }
|
||||
|
||||
provider->DrawSubtitles(*frame, time);
|
||||
|
@ -200,13 +198,13 @@ wxDEFINE_EVENT(EVT_FRAME_READY, FrameReadyEvent);
|
|||
wxDEFINE_EVENT(EVT_VIDEO_ERROR, VideoProviderErrorEvent);
|
||||
wxDEFINE_EVENT(EVT_SUBTITLES_ERROR, SubtitlesProviderErrorEvent);
|
||||
|
||||
VideoProviderErrorEvent::VideoProviderErrorEvent(wxString msg)
|
||||
: agi::Exception(STD_STR(msg), NULL)
|
||||
VideoProviderErrorEvent::VideoProviderErrorEvent(VideoProviderError const& err)
|
||||
: agi::Exception(err.GetMessage(), &err)
|
||||
{
|
||||
SetEventType(EVT_VIDEO_ERROR);
|
||||
}
|
||||
SubtitlesProviderErrorEvent::SubtitlesProviderErrorEvent(wxString msg)
|
||||
: agi::Exception(STD_STR(msg), NULL)
|
||||
SubtitlesProviderErrorEvent::SubtitlesProviderErrorEvent(wxString err)
|
||||
: agi::Exception(err, NULL)
|
||||
{
|
||||
SetEventType(EVT_SUBTITLES_ERROR);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
class AssFile;
|
||||
class SubtitlesProvider;
|
||||
class VideoProvider;
|
||||
class VideoProviderError;
|
||||
|
||||
/// @class ThreadedFrameSource
|
||||
/// @brief An asynchronous video decoding and subtitle rendering wrapper
|
||||
|
@ -155,7 +156,7 @@ public:
|
|||
const char * GetName() const { return "video/error"; }
|
||||
wxEvent *Clone() const { return new VideoProviderErrorEvent(*this); };
|
||||
agi::Exception *Copy() const { return new VideoProviderErrorEvent(*this); };
|
||||
VideoProviderErrorEvent(wxString msg);
|
||||
VideoProviderErrorEvent(VideoProviderError const& err);
|
||||
};
|
||||
|
||||
class SubtitlesProviderErrorEvent : public wxEvent, public agi::Exception {
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
/// @ingroup main_ui video
|
||||
///
|
||||
|
||||
|
||||
////////////
|
||||
// Includes
|
||||
#include "config.h"
|
||||
|
||||
#ifndef AGI_PRE
|
||||
|
@ -44,7 +41,6 @@
|
|||
#include <wx/mimetype.h>
|
||||
#include <wx/rawbmp.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/tglbtn.h>
|
||||
#endif
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#include "video_box.h"
|
||||
#include "video_context.h"
|
||||
#include "video_display.h"
|
||||
#include "video_frame.h"
|
||||
|
||||
/// IDs
|
||||
enum {
|
||||
|
@ -196,11 +197,13 @@ void VideoContext::SetVideo(const wxString &filename) {
|
|||
|
||||
UpdateDisplays(true);
|
||||
}
|
||||
catch (const wchar_t *e) {
|
||||
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
||||
catch (agi::UserCancelException const&) { }
|
||||
catch (agi::FileNotAccessibleError const& err) {
|
||||
config::mru->Remove("Video", STD_STR(filename));
|
||||
wxMessageBox(lagi_wxString(err.GetMessage()), L"Error setting video", wxICON_ERROR | wxOK);
|
||||
}
|
||||
catch (const wxString &e) {
|
||||
wxMessageBox(e,_T("Error setting video"),wxICON_ERROR | wxOK);
|
||||
catch (VideoProviderError const& err) {
|
||||
wxMessageBox(lagi_wxString(err.GetMessage()), L"Error setting video", wxICON_ERROR | wxOK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,17 +49,9 @@
|
|||
#error "Aegisub requires wxWidgets to be compiled with OpenGL support."
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/GL.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#include <libaegisub/vfr.h>
|
||||
#include "video_frame.h"
|
||||
|
||||
class AegiVideoFrame;
|
||||
class SubtitlesGrid;
|
||||
class AudioProvider;
|
||||
class AudioDisplay;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#endif
|
||||
|
||||
#include "charset_conv.h"
|
||||
#include "compat.h"
|
||||
#include "gl_wrap.h"
|
||||
#include <libaegisub/log.h>
|
||||
#include "mkv_wrap.h"
|
||||
|
@ -51,114 +52,93 @@
|
|||
#include "video_context.h"
|
||||
#include "video_provider_avs.h"
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param _filename
|
||||
///
|
||||
AvisynthVideoProvider::AvisynthVideoProvider(wxString _filename) {
|
||||
bool mpeg2dec3_priority = true;
|
||||
RGB32Video = NULL;
|
||||
num_frames = 0;
|
||||
last_fnum = -1;
|
||||
KeyFrames.clear();
|
||||
|
||||
RGB32Video = OpenVideo(_filename,mpeg2dec3_priority);
|
||||
AvisynthVideoProvider::AvisynthVideoProvider(wxString filename) try
|
||||
: usedDirectShow(false)
|
||||
, decoderName(_("Unknown"))
|
||||
, num_frames(0)
|
||||
, last_fnum(-1)
|
||||
, RGB32Video(NULL)
|
||||
{
|
||||
RGB32Video = OpenVideo(filename);
|
||||
|
||||
vi = RGB32Video->GetVideoInfo();
|
||||
}
|
||||
catch (AvisynthError const& err) {
|
||||
throw VideoOpenError("Avisynth error: " + std::string(err.msg));
|
||||
}
|
||||
|
||||
/// @brief Destructor
|
||||
///
|
||||
AvisynthVideoProvider::~AvisynthVideoProvider() {
|
||||
iframe.Clear();
|
||||
}
|
||||
|
||||
/// @brief Actually open the video into Avisynth
|
||||
/// @param _filename
|
||||
/// @param mpeg2dec3_priority
|
||||
/// @return
|
||||
///
|
||||
PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priority) {
|
||||
wxMutexLocker lock(AviSynthMutex);
|
||||
AVSValue script;
|
||||
|
||||
usedDirectShow = false;
|
||||
decoderName = _("Unknown");
|
||||
|
||||
wxString extension = _filename.Right(4);
|
||||
extension.LowerCase();
|
||||
|
||||
try {
|
||||
// Prepare filename
|
||||
//char *videoFilename = env->SaveString(_filename.mb_str(wxConvLocal));
|
||||
wxFileName fname(_filename);
|
||||
AVSValue AvisynthVideoProvider::Open(wxFileName const& fname, wxString const& extension) {
|
||||
char *videoFilename = env->SaveString(fname.GetShortPath().mb_str(csConvLocal));
|
||||
|
||||
// Avisynth file, just import it
|
||||
if (extension == _T(".avs")) {
|
||||
if (extension == L".avs") {
|
||||
LOG_I("avisynth/video") << "Opening .avs file with Import";
|
||||
script = env->Invoke("Import", videoFilename);
|
||||
decoderName = _T("Import");
|
||||
decoderName = L"Import";
|
||||
return env->Invoke("Import", videoFilename);
|
||||
}
|
||||
|
||||
// Open avi file with AviSource
|
||||
else if (extension == _T(".avi")) {
|
||||
if (extension == L".avi") {
|
||||
LOG_I("avisynth/video") << "Opening .avi file with AviSource";
|
||||
try {
|
||||
const char *argnames[2] = { 0, "audio" };
|
||||
AVSValue args[2] = { videoFilename, false };
|
||||
script = env->Invoke("AviSource", AVSValue(args,2), argnames);
|
||||
decoderName = _T("AviSource");
|
||||
decoderName = L"AviSource";
|
||||
return env->Invoke("AviSource", AVSValue(args,2), argnames);
|
||||
}
|
||||
|
||||
// On Failure, fallback to DSS
|
||||
catch (AvisynthError &) {
|
||||
LOG_I("avisynth/video") << "Failed to open .avi file with AviSource, switching to DirectShowSource";
|
||||
goto directshowOpen;
|
||||
}
|
||||
}
|
||||
|
||||
// Open d2v with mpeg2dec3
|
||||
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Dec3_Mpeg2Source") && mpeg2dec3_priority) {
|
||||
if (extension == L".d2v" && env->FunctionExists("Mpeg2Dec3_Mpeg2Source")) {
|
||||
LOG_I("avisynth/video") << "Opening .d2v file with Mpeg2Dec3_Mpeg2Source";
|
||||
script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
|
||||
decoderName = _T("Mpeg2Dec3_Mpeg2Source");
|
||||
AVSValue script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
|
||||
decoderName = L"Mpeg2Dec3_Mpeg2Source";
|
||||
|
||||
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
||||
if (env->FunctionExists("SetPlanarLegacyAlignment")) {
|
||||
AVSValue args[2] = { script, true };
|
||||
script = env->Invoke("SetPlanarLegacyAlignment", AVSValue(args,2));
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
// If that fails, try opening it with DGDecode
|
||||
else if (extension == _T(".d2v") && env->FunctionExists("DGDecode_Mpeg2Source")) {
|
||||
if (extension == L".d2v" && env->FunctionExists("DGDecode_Mpeg2Source")) {
|
||||
LOG_I("avisynth/video") << "Opening .d2v file with DGDecode_Mpeg2Source";
|
||||
script = env->Invoke("Mpeg2Source", videoFilename);
|
||||
decoderName = _T("DGDecode_Mpeg2Source");
|
||||
decoderName = L"DGDecode_Mpeg2Source";
|
||||
return env->Invoke("Mpeg2Source", videoFilename);
|
||||
|
||||
//note that DGDecode will also have issues like if the version is too ancient but no sane person
|
||||
//would use that anyway
|
||||
}
|
||||
|
||||
else if (extension == _T(".d2v") && env->FunctionExists("Mpeg2Source")) {
|
||||
if (extension == L".d2v" && env->FunctionExists("Mpeg2Source")) {
|
||||
LOG_I("avisynth/video") << "Opening .d2v file with other Mpeg2Source";
|
||||
script = env->Invoke("Mpeg2Source", videoFilename);
|
||||
decoderName = _T("Mpeg2Source");
|
||||
AVSValue script = env->Invoke("Mpeg2Source", videoFilename);
|
||||
decoderName = L"Mpeg2Source";
|
||||
|
||||
//if avisynth is 2.5.7 beta 2 or newer old mpeg2decs will crash without this
|
||||
if (env->FunctionExists("SetPlanarLegacyAlignment"))
|
||||
script = env->Invoke("SetPlanarLegacyAlignment", script);
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
// Some other format, such as mkv, mp4, ogm... try both flavors of DirectShowSource
|
||||
else {
|
||||
directshowOpen:
|
||||
|
||||
// Try loading DirectShowSource2
|
||||
bool dss2 = false;
|
||||
if (env->FunctionExists("dss2")) dss2 = true;
|
||||
if (!dss2) {
|
||||
if (!env->FunctionExists("dss2")) {
|
||||
wxFileName dss2path(StandardPaths::DecodePath(_T("?data/avss.dll")));
|
||||
if (dss2path.FileExists()) {
|
||||
env->Invoke("LoadPlugin",env->SaveString(dss2path.GetFullPath().mb_str(csConvLocal)));
|
||||
|
@ -166,16 +146,13 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
|||
}
|
||||
|
||||
// If DSS2 loaded properly, try using it
|
||||
dss2 = false;
|
||||
if (env->FunctionExists("dss2")) {
|
||||
LOG_I("avisynth/video") << "Opening video with DSS2";
|
||||
script = env->Invoke("DSS2", videoFilename);
|
||||
dss2 = true;
|
||||
decoderName = _T("DSS2");
|
||||
LOG_I("avisynth/video") << "Opening file with DSS2";
|
||||
decoderName = L"DSS2";
|
||||
return env->Invoke("DSS2", videoFilename);
|
||||
}
|
||||
|
||||
// Try DirectShowSource
|
||||
if (!dss2) {
|
||||
// Load DirectShowSource.dll from app dir if it exists
|
||||
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
|
||||
if (dsspath.FileExists()) {
|
||||
|
@ -186,39 +163,48 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
|||
if (env->FunctionExists("DirectShowSource")) {
|
||||
const char *argnames[3] = { 0, "video", "audio" };
|
||||
AVSValue args[3] = { videoFilename, true, false };
|
||||
LOG_I("avisynth/video") << "Opening video with DirectShowSource";
|
||||
script = env->Invoke("DirectShowSource", AVSValue(args,3), argnames);
|
||||
usedDirectShow = true;
|
||||
decoderName = _T("DirectShowSource");
|
||||
decoderName = L"DirectShowSource";
|
||||
LOG_I("avisynth/video") << "Opening file with DirectShowSource";
|
||||
return env->Invoke("DirectShowSource", AVSValue(args,3), argnames);
|
||||
}
|
||||
|
||||
// Failed to find a suitable function
|
||||
else {
|
||||
LOG_E("avisynth/video") << "DSS function not found";
|
||||
throw AvisynthError("No function suitable for opening the video found");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw VideoNotSupported("No function suitable for opening the video found");
|
||||
}
|
||||
|
||||
// Catch errors
|
||||
catch (AvisynthError &err) {
|
||||
LOG_E("avisynth/video") << "Avisynth error: " << err.msg;
|
||||
throw _T("AviSynth error: ") + wxString(err.msg,csConvLocal);
|
||||
/// @brief Actually open the video into Avisynth
|
||||
/// @param _filename
|
||||
/// @return
|
||||
///
|
||||
PClip AvisynthVideoProvider::OpenVideo(wxString filename) {
|
||||
wxMutexLocker lock(AviSynthMutex);
|
||||
|
||||
wxFileName fname(filename);
|
||||
if (!fname.FileExists())
|
||||
throw agi::FileNotFoundError(STD_STR(filename));
|
||||
|
||||
AVSValue script;
|
||||
wxString extension = filename.Right(4).Lower();
|
||||
try {
|
||||
script = Open(fname, extension);
|
||||
}
|
||||
catch (AvisynthError const& err) {
|
||||
throw VideoOpenError("Avisynth error: " + std::string(err.msg));
|
||||
}
|
||||
|
||||
// Check if video was loaded properly
|
||||
if (!script.IsClip() || !script.AsClip()->GetVideoInfo().HasVideo()) {
|
||||
LOG_E("avisynth/video") << "AvisynthVideoProvider::OpenVideo: No suitable video found";
|
||||
throw _T("Avisynth: No usable video found in ") + _filename;
|
||||
throw VideoNotSupported("No usable video found");
|
||||
}
|
||||
|
||||
// Read keyframes and timecodes from MKV file
|
||||
bool mkvOpen = MatroskaWrapper::wrapper.IsOpen();
|
||||
KeyFrames.clear();
|
||||
if (extension == _T(".mkv") || mkvOpen) {
|
||||
if (extension == L".mkv" || mkvOpen) {
|
||||
// Parse mkv
|
||||
if (!mkvOpen) MatroskaWrapper::wrapper.Open(_filename);
|
||||
if (!mkvOpen) MatroskaWrapper::wrapper.Open(filename);
|
||||
|
||||
// Get keyframes
|
||||
KeyFrames = MatroskaWrapper::wrapper.GetKeyFrames();
|
||||
|
@ -230,9 +216,9 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
|||
}
|
||||
// check if we have windows, if so we can load keyframes from AVI files using VFW
|
||||
#ifdef __WINDOWS__
|
||||
else if (extension == _T(".avi")) {
|
||||
else if (extension == L".avi") {
|
||||
KeyFrames.clear();
|
||||
KeyFrames = VFWWrapper::GetKeyFrames(_filename);
|
||||
KeyFrames = VFWWrapper::GetKeyFrames(filename);
|
||||
}
|
||||
#endif /* __WINDOWS__ */
|
||||
|
||||
|
@ -261,8 +247,6 @@ PClip AvisynthVideoProvider::OpenVideo(wxString _filename, bool mpeg2dec3_priori
|
|||
return (env->Invoke("Cache", script)).AsClip();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Actually get a frame
|
||||
/// @param _n
|
||||
/// @return
|
||||
|
|
|
@ -78,10 +78,11 @@ class AvisynthVideoProvider: public VideoProvider, AviSynthWrapper {
|
|||
/// DOCME
|
||||
PClip RGB32Video;
|
||||
|
||||
PClip OpenVideo(wxString _filename, bool mpeg2dec3_priority = true);
|
||||
PClip OpenVideo(wxString filename);
|
||||
AVSValue Open(wxFileName const& fname, wxString const& extension);
|
||||
|
||||
public:
|
||||
AvisynthVideoProvider(wxString _filename);
|
||||
AvisynthVideoProvider(wxString filename);
|
||||
~AvisynthVideoProvider();
|
||||
|
||||
const AegiVideoFrame GetFrame(int n);
|
||||
|
|
|
@ -79,6 +79,4 @@ public:
|
|||
virtual std::vector<int> GetKeyFrames() const { return master->GetKeyFrames(); }
|
||||
virtual wxString GetWarning() const { return master->GetWarning(); }
|
||||
virtual wxString GetDecoderName() const { return master->GetDecoderName(); }
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -122,12 +122,12 @@ DummyVideoProvider::DummyVideoProvider(wxString filename)
|
|||
{
|
||||
wxString params;
|
||||
if (!filename.StartsWith(_T("?dummy:"), ¶ms)) {
|
||||
throw _T("Attempted creating dummy video provider with non-dummy filename");
|
||||
throw agi::FileNotFoundError("Attempted creating dummy video provider with non-dummy filename");
|
||||
}
|
||||
|
||||
wxStringTokenizer t(params, _T(":"));
|
||||
if (t.CountTokens() < 7) {
|
||||
throw _T("Too few fields in dummy video parameter list");
|
||||
throw VideoOpenError("Too few fields in dummy video parameter list");
|
||||
}
|
||||
|
||||
double fps;
|
||||
|
@ -136,37 +136,37 @@ DummyVideoProvider::DummyVideoProvider(wxString filename)
|
|||
|
||||
wxString field = t.GetNextToken();
|
||||
if (!field.ToDouble(&fps)) {
|
||||
throw _T("Unable to parse fps field in dummy video parameter list");
|
||||
throw VideoOpenError("Unable to parse fps field in dummy video parameter list");
|
||||
}
|
||||
|
||||
field = t.GetNextToken();
|
||||
if (!field.ToLong(&_frames)) {
|
||||
throw _T("Unable to parse framecount field in dummy video parameter list");
|
||||
throw VideoOpenError("Unable to parse framecount field in dummy video parameter list");
|
||||
}
|
||||
|
||||
field = t.GetNextToken();
|
||||
if (!field.ToLong(&_width)) {
|
||||
throw _T("Unable to parse width field in dummy video parameter list");
|
||||
throw VideoOpenError("Unable to parse width field in dummy video parameter list");
|
||||
}
|
||||
|
||||
field = t.GetNextToken();
|
||||
if (!field.ToLong(&_height)) {
|
||||
throw _T("Unable to parse height field in dummy video parameter list");
|
||||
throw VideoOpenError("Unable to parse height field in dummy video parameter list");
|
||||
}
|
||||
|
||||
field = t.GetNextToken();
|
||||
if (!field.ToLong(&red)) {
|
||||
throw _T("Unable to parse red colour field in dummy video parameter list");
|
||||
throw VideoOpenError("Unable to parse red colour field in dummy video parameter list");
|
||||
}
|
||||
|
||||
field = t.GetNextToken();
|
||||
if (!field.ToLong(&green)) {
|
||||
throw _T("Unable to parse green colour field in dummy video parameter list");
|
||||
throw VideoOpenError("Unable to parse green colour field in dummy video parameter list");
|
||||
}
|
||||
|
||||
field = t.GetNextToken();
|
||||
if (!field.ToLong(&blue)) {
|
||||
throw _T("Unable to parse bluecolour field in dummy video parameter list");
|
||||
throw VideoOpenError("Unable to parse blue colour field in dummy video parameter list");
|
||||
}
|
||||
|
||||
field = t.GetNextToken();
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
#endif
|
||||
|
||||
#include "aegisub_endian.h"
|
||||
#include "include/aegisub/aegisub.h"
|
||||
#include "compat.h"
|
||||
#include "main.h"
|
||||
#include "video_context.h"
|
||||
#include "video_provider_ffmpegsource.h"
|
||||
|
@ -60,35 +60,41 @@
|
|||
|
||||
/// @brief Constructor
|
||||
/// @param filename The filename to open
|
||||
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
||||
COMInited = false;
|
||||
FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename)
|
||||
: VideoSource(NULL)
|
||||
, VideoInfo(NULL)
|
||||
, Width(-1)
|
||||
, Height(-1)
|
||||
, FrameNumber(-1)
|
||||
, COMInited(false)
|
||||
{
|
||||
#ifdef WIN32
|
||||
HRESULT res;
|
||||
res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
HRESULT res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
if (SUCCEEDED(res))
|
||||
COMInited = true;
|
||||
else if (res != RPC_E_CHANGED_MODE)
|
||||
throw _T("FFmpegSource video provider: COM initialization failure");
|
||||
throw VideoOpenError("COM initialization failure");
|
||||
#endif
|
||||
// initialize ffmpegsource
|
||||
// FIXME: CPU detection?
|
||||
FFMS_Init(0);
|
||||
|
||||
// clean up variables
|
||||
VideoSource = NULL;
|
||||
FrameNumber = -1;
|
||||
ErrInfo.Buffer = FFMSErrMsg;
|
||||
ErrInfo.BufferSize = sizeof(FFMSErrMsg);
|
||||
ErrInfo.ErrorType = FFMS_ERROR_SUCCESS;
|
||||
ErrInfo.SubType = FFMS_ERROR_SUCCESS;
|
||||
ErrorMsg = _T("FFmpegSource video provider: ");
|
||||
|
||||
SetLogLevel();
|
||||
|
||||
// and here we go
|
||||
try {
|
||||
LoadVideo(filename);
|
||||
} catch (...) {
|
||||
}
|
||||
catch (wxString const& err) {
|
||||
Close();
|
||||
throw VideoOpenError(STD_STR(err));
|
||||
}
|
||||
catch (...) {
|
||||
Close();
|
||||
throw;
|
||||
}
|
||||
|
@ -98,32 +104,22 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(wxString filename) {
|
|||
/// @brief Destructor
|
||||
FFmpegSourceVideoProvider::~FFmpegSourceVideoProvider() {
|
||||
Close();
|
||||
#ifdef WIN32
|
||||
if (COMInited)
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// @brief Opens video
|
||||
/// @param filename The filename to open
|
||||
void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
||||
// make sure we don't have anything messy lying around
|
||||
Close();
|
||||
|
||||
wxString FileNameShort = wxFileName(filename).GetShortPath();
|
||||
|
||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(FileNameShort.utf8_str(), &ErrInfo);
|
||||
if (Indexer == NULL) {
|
||||
// error messages that can possibly contain a filename use this method instead of
|
||||
// wxString::Format because they may contain utf8 characters
|
||||
ErrorMsg.Append(_T("Failed to create indexer: ")).Append(wxString(ErrInfo.Buffer, wxConvUTF8));
|
||||
throw ErrorMsg;
|
||||
throw agi::FileNotFoundError(ErrInfo.Buffer);
|
||||
}
|
||||
|
||||
std::map<int,wxString> TrackList = GetTracksOfType(Indexer, FFMS_TYPE_VIDEO);
|
||||
if (TrackList.size() <= 0)
|
||||
throw _T("FFmpegSource video provider: no video tracks found");
|
||||
throw VideoNotSupported("no video tracks found");
|
||||
|
||||
// initialize the track number to an invalid value so we can detect later on
|
||||
// whether the user actually had to choose a track or not
|
||||
|
@ -132,7 +128,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
|||
TrackNumber = AskForTrackSelection(TrackList, FFMS_TYPE_VIDEO);
|
||||
// if it's still -1 here, user pressed cancel
|
||||
if (TrackNumber == -1)
|
||||
throw _T("FFmpegSource video provider: video loading cancelled by user");
|
||||
throw agi::UserCancelException("video loading cancelled by user");
|
||||
}
|
||||
|
||||
// generate a name for the cache file
|
||||
|
@ -169,11 +165,9 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
|||
try {
|
||||
// ignore audio decoding errors here, we don't care right now
|
||||
Index = DoIndexing(Indexer, CacheName, TrackMask, FFMS_IEH_IGNORE);
|
||||
} catch (wxString temp) {
|
||||
ErrorMsg.Append(temp);
|
||||
throw ErrorMsg;
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
catch (wxString err) {
|
||||
throw VideoOpenError(STD_STR(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,15 +186,14 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
|||
if (TrackNumber < 0) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
ErrorMsg.Append(wxString::Format(_T("Couldn't find any video tracks: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw VideoNotSupported(std::string("Couldn't find any video tracks: ") + ErrInfo.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// set thread count
|
||||
int Threads = OPT_GET("Provider/Video/FFmpegSource/Decoding Threads")->GetInt();
|
||||
if (Threads < 1)
|
||||
throw _T("FFmpegSource video provider: invalid decoding thread count");
|
||||
throw VideoOpenError("invalid decoding thread count");
|
||||
|
||||
// set seekmode
|
||||
// TODO: give this its own option?
|
||||
|
@ -214,8 +207,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
|||
FFMS_DestroyIndex(Index);
|
||||
Index = NULL;
|
||||
if (VideoSource == NULL) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to open video track: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw VideoOpenError(std::string("Failed to open video track: ") + ErrInfo.Buffer);
|
||||
}
|
||||
|
||||
// load video properties
|
||||
|
@ -223,24 +215,22 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
|||
|
||||
const FFMS_Frame *TempFrame = FFMS_GetFrame(VideoSource, 0, &ErrInfo);
|
||||
if (TempFrame == NULL) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to decode first frame: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw VideoOpenError(std::string("Failed to decode first frame: ") + ErrInfo.Buffer);
|
||||
}
|
||||
Width = TempFrame->EncodedWidth;
|
||||
Height = TempFrame->EncodedHeight;
|
||||
|
||||
if (FFMS_SetOutputFormatV(VideoSource, 1LL << FFMS_GetPixFmt("bgra"), Width, Height, FFMS_RESIZER_BICUBIC, &ErrInfo)) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to set output format: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw VideoOpenError(std::string("Failed to set output format: ") + ErrInfo.Buffer);
|
||||
}
|
||||
|
||||
// get frame info data
|
||||
FFMS_Track *FrameData = FFMS_GetTrackFromVideo(VideoSource);
|
||||
if (FrameData == NULL)
|
||||
throw _T("FFmpegSource video provider: failed to get frame data");
|
||||
throw VideoOpenError("failed to get frame data");
|
||||
const FFMS_TrackTimeBase *TimeBase = FFMS_GetTimeBase(FrameData);
|
||||
if (TimeBase == NULL)
|
||||
throw _T("FFmpegSource video provider: failed to get track time base");
|
||||
throw VideoOpenError("failed to get track time base");
|
||||
|
||||
const FFMS_FrameInfo *CurFrameData;
|
||||
|
||||
|
@ -249,8 +239,7 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
|||
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
||||
CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum);
|
||||
if (CurFrameData == NULL) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Couldn't get info about frame %d"), CurFrameNum));
|
||||
throw ErrorMsg;
|
||||
throw VideoOpenError(STD_STR(wxString::Format(L"Couldn't get info about frame %d", CurFrameNum)));
|
||||
}
|
||||
|
||||
// keyframe?
|
||||
|
@ -269,13 +258,11 @@ void FFmpegSourceVideoProvider::LoadVideo(wxString filename) {
|
|||
/// @brief Close video
|
||||
///
|
||||
void FFmpegSourceVideoProvider::Close() {
|
||||
FFMS_DestroyVideoSource(VideoSource);
|
||||
VideoSource = NULL;
|
||||
|
||||
KeyFramesList.clear();
|
||||
FrameNumber = -1;
|
||||
Timecodes = agi::vfr::Framerate();
|
||||
CurFrame.Clear();
|
||||
if (VideoSource) FFMS_DestroyVideoSource(VideoSource);
|
||||
#ifdef WIN32
|
||||
if (COMInited)
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief Get frame
|
||||
|
@ -295,8 +282,7 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n) {
|
|||
// decode frame
|
||||
const FFMS_Frame *SrcFrame = FFMS_GetFrame(VideoSource, n, &ErrInfo);
|
||||
if (SrcFrame == NULL) {
|
||||
ErrorMsg.Append(wxString::Format(_T("Failed to retrieve frame: %s"), ErrInfo.Buffer));
|
||||
throw ErrorMsg;
|
||||
throw VideoDecodeError(std::string("Failed to retrieve frame:") + ErrInfo.Buffer);
|
||||
}
|
||||
|
||||
CurFrame.SetTo(SrcFrame->Data, Width, Height, SrcFrame->Linesize, FORMAT_RGB32);
|
||||
|
|
|
@ -61,7 +61,6 @@ private:
|
|||
|
||||
char FFMSErrMsg[1024]; /// FFMS error message
|
||||
FFMS_ErrorInfo ErrInfo; /// FFMS error codes/messages
|
||||
wxString ErrorMsg; /// wx-ified error message
|
||||
|
||||
void LoadVideo(wxString filename);
|
||||
void Close();
|
||||
|
|
|
@ -58,53 +58,51 @@
|
|||
/// @return
|
||||
///
|
||||
VideoProvider *VideoProviderFactory::GetProvider(wxString video) {
|
||||
// First check special case of dummy video
|
||||
if (video.StartsWith(_T("?dummy:"))) {
|
||||
return new DummyVideoProvider(video.wc_str());
|
||||
}
|
||||
|
||||
try {
|
||||
VideoProvider *y4m_provider = new YUV4MPEGVideoProvider(video);
|
||||
if (y4m_provider)
|
||||
y4m_provider = new VideoProviderCache(y4m_provider);
|
||||
return y4m_provider;
|
||||
}
|
||||
catch (wxString temp) {
|
||||
LOG_E("manager/video/provider/yuv4mpeg") << "Provider creation failed with reason: "<< temp.c_str() << " trying other providers";
|
||||
}
|
||||
catch (...) {
|
||||
LOG_E("manager/video/provider/yuv4mpeg") << "Provider creation failed (unknown reason) trying other providers";
|
||||
}
|
||||
|
||||
// List of providers
|
||||
std::vector<std::string> list = GetClasses(OPT_GET("Video/Provider")->GetString());
|
||||
if (video.StartsWith("?dummy")) list.insert(list.begin(), "Dummy");
|
||||
list.insert(list.begin(), "YUV4MPEG");
|
||||
|
||||
// None available
|
||||
if (list.empty()) throw _T("No video providers are available.");
|
||||
|
||||
// Get provider
|
||||
wxString error;
|
||||
for (unsigned int i=0;i<list.size();i++) {
|
||||
bool fileFound = false;
|
||||
bool fileSupported = false;
|
||||
std::string errors;
|
||||
errors.reserve(1024);
|
||||
for (int i = 0; i < (signed)list.size(); ++i) {
|
||||
try {
|
||||
// Create provider
|
||||
VideoProvider *provider = Create(list[i], video);
|
||||
if (provider) {
|
||||
// Cache if necessary
|
||||
LOG_I("manager/video/provider") << list[i] << ": opened " << STD_STR(video);
|
||||
if (provider->WantsCaching()) {
|
||||
provider = new VideoProviderCache(provider);
|
||||
return new VideoProviderCache(provider);
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
catch (agi::FileNotFoundError const&) {
|
||||
std::string err = list[i] + ": " + STD_STR(video) + " not found.";
|
||||
errors += err + "\n";
|
||||
LOG_D("manager/video/provider") << err;
|
||||
// Keep trying other providers as this one may just not be able to
|
||||
// open a valid path
|
||||
}
|
||||
catch (VideoNotSupported const&) {
|
||||
fileFound = true;
|
||||
std::string err = list[i] + ": " + STD_STR(video) + " is not in a supported format.\n";
|
||||
errors += err + "\n";
|
||||
LOG_D("manager/video/provider") << err;
|
||||
}
|
||||
catch (VideoOpenError const& ex) {
|
||||
fileSupported = true;
|
||||
std::string err = list[i] + ": " + ex.GetMessage();
|
||||
errors += err + "\n";
|
||||
LOG_D("manager/video/provider") << err;
|
||||
}
|
||||
catch (wxString err) { error += list[i] + _T(" factory: ") + err + _T("\n"); }
|
||||
catch (const wxChar *err) { error += list[i] + _T(" factory: ") + wxString(err) + _T("\n"); }
|
||||
catch (...) { error += list[i] + _T(" factory: Unknown error\n"); }
|
||||
}
|
||||
|
||||
// Failed
|
||||
throw error;
|
||||
// No provider could open the file
|
||||
LOG_E("manager/video/provider") << "Could not open " << STD_STR(video);
|
||||
std::string msg = "Could not open " + STD_STR(video) + ":\n" + errors;
|
||||
|
||||
if (!fileFound) throw agi::FileNotFoundError(STD_STR(video));
|
||||
if (!fileSupported) throw VideoNotSupported(msg);
|
||||
throw VideoOpenError(msg);
|
||||
}
|
||||
|
||||
/// @brief Register all providers
|
||||
|
@ -120,5 +118,4 @@ void VideoProviderFactory::RegisterProviders() {
|
|||
Register<YUV4MPEGVideoProvider>("YUV4MPEG", true);
|
||||
}
|
||||
|
||||
/// DOCME
|
||||
template<> VideoProviderFactory::map *FactoryBase<VideoProvider *(*)(wxString)>::classes = NULL;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "video_provider_yuv4mpeg.h"
|
||||
|
||||
// All of this cstdio bogus is because of one reason and one reason only:
|
||||
|
@ -49,53 +50,22 @@
|
|||
#define ftello _ftelli64
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// @brief Constructor
|
||||
/// @param filename The filename to open
|
||||
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString filename) {
|
||||
sf = NULL;
|
||||
w = 0;
|
||||
h = 0;
|
||||
cur_fn = -1;
|
||||
inited = false;
|
||||
pixfmt = Y4M_PIXFMT_NONE;
|
||||
imode = Y4M_ILACE_NOTSET;
|
||||
num_frames = -1;
|
||||
YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString fname)
|
||||
: sf(NULL)
|
||||
, w (0)
|
||||
, h (0)
|
||||
, cur_fn(-1)
|
||||
, pixfmt(Y4M_PIXFMT_NONE)
|
||||
, imode(Y4M_ILACE_NOTSET)
|
||||
, num_frames(-1)
|
||||
{
|
||||
fps_rat.num = -1;
|
||||
fps_rat.den = 1;
|
||||
seek_table.clear();
|
||||
|
||||
errmsg = _T("YUV4MPEG video provider: ");
|
||||
|
||||
try {
|
||||
LoadVideo(filename);
|
||||
}
|
||||
catch (wxString temp) {
|
||||
Close();
|
||||
errmsg.Append(temp);
|
||||
throw errmsg;
|
||||
}
|
||||
catch (...) {
|
||||
Close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() {
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
/// @brief Open a video file
|
||||
/// @param _filename The video file to open
|
||||
void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) {
|
||||
Close();
|
||||
|
||||
wxString filename = wxFileName(_filename).GetShortPath();
|
||||
wxString filename = wxFileName(fname).GetShortPath();
|
||||
|
||||
#ifdef WIN32
|
||||
sf = _wfopen(filename.wc_str(), _T("rb"));
|
||||
|
@ -103,15 +73,14 @@ void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) {
|
|||
sf = fopen(filename.utf8_str(), "rb");
|
||||
#endif
|
||||
|
||||
if (sf == NULL)
|
||||
throw wxString::Format(_T("Failed to open file"));
|
||||
if (sf == NULL) throw agi::FileNotFoundError(STD_STR(fname));
|
||||
|
||||
CheckFileFormat();
|
||||
|
||||
ParseFileHeader(ReadHeader(0, false));
|
||||
|
||||
if (w <= 0 || h <= 0)
|
||||
throw wxString(_T("Invalid resolution"));
|
||||
throw VideoOpenError("Invalid resolution");
|
||||
if (fps_rat.num <= 0 || fps_rat.den <= 0) {
|
||||
fps_rat.num = 25;
|
||||
fps_rat.den = 1;
|
||||
|
@ -132,42 +101,42 @@ void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) {
|
|||
chroma_sz = (w * h) >> 1; break;
|
||||
/// @todo add support for more pixel formats
|
||||
default:
|
||||
throw wxString(_T("Unsupported pixel format"));
|
||||
throw VideoOpenError("Unsupported pixel format");
|
||||
}
|
||||
frame_sz = luma_sz + chroma_sz*2;
|
||||
|
||||
num_frames = IndexFile();
|
||||
if (num_frames <= 0 || seek_table.empty())
|
||||
throw wxString(_T("Unable to determine file length"));
|
||||
throw VideoOpenError("Unable to determine file length");
|
||||
cur_fn = 0;
|
||||
|
||||
fseeko(sf, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
/// @brief Closes the currently open file (if any) and resets reader state
|
||||
void YUV4MPEGVideoProvider::Close() {
|
||||
seek_table.clear();
|
||||
if (sf)
|
||||
fclose(sf);
|
||||
sf = NULL;
|
||||
catch (...) {
|
||||
if (sf) fclose(sf);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() {
|
||||
if (sf) fclose(sf);
|
||||
}
|
||||
|
||||
/// @brief Checks if the file is an YUV4MPEG file or not
|
||||
/// Note that it reports the error by throwing an exception,
|
||||
/// not by returning a false value.
|
||||
void YUV4MPEGVideoProvider::CheckFileFormat() {
|
||||
char buf[10];
|
||||
if (fread(buf, 10, 1, sf) != 1)
|
||||
throw wxString(_T("CheckFileFormat: Failed reading header"));
|
||||
throw VideoNotSupported("CheckFileFormat: Failed reading header");
|
||||
if (strncmp("YUV4MPEG2 ", buf, 10))
|
||||
throw wxString(_T("CheckFileFormat: File is not a YUV4MPEG file (bad magic)"));
|
||||
throw VideoNotSupported("CheckFileFormat: File is not a YUV4MPEG file (bad magic)");
|
||||
|
||||
fseeko(sf, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
/// @brief Read a frame or file header at a given file position
|
||||
/// @param startpos The byte offset at where to start reading
|
||||
/// @param reset_pos If true, the function will reset the file position to what it was before the function call before returning
|
||||
|
@ -175,17 +144,17 @@ void YUV4MPEGVideoProvider::CheckFileFormat() {
|
|||
std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool reset_pos) {
|
||||
int64_t oldpos = ftello(sf);
|
||||
std::vector<wxString> tags;
|
||||
wxString curtag = _T("");
|
||||
wxString curtag;
|
||||
int bytesread = 0;
|
||||
int buf;
|
||||
|
||||
if (fseeko(sf, startpos, SEEK_SET))
|
||||
throw wxString::Format(_T("YUV4MPEG video provider: ReadHeader: failed seeking to position %d"), startpos);
|
||||
throw VideoOpenError(STD_STR(wxString::Format(L"YUV4MPEG video provider: ReadHeader: failed seeking to position %d", startpos)));
|
||||
|
||||
// read header until terminating newline (0x0A) is found
|
||||
while ((buf = fgetc(sf)) != 0x0A) {
|
||||
if (ferror(sf))
|
||||
throw wxString(_T("ReadHeader: Failed to read from file"));
|
||||
throw VideoOpenError("ReadHeader: Failed to read from file");
|
||||
if (feof(sf)) {
|
||||
// you know, this is one of the places where it would be really nice
|
||||
// to be able to throw an exception object that tells the caller that EOF was reached
|
||||
|
@ -195,9 +164,9 @@ std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool r
|
|||
|
||||
// some basic low-effort sanity checking
|
||||
if (buf == 0x00)
|
||||
throw wxString(_T("ReadHeader: Malformed header (unexpected NUL)"));
|
||||
throw VideoOpenError("ReadHeader: Malformed header (unexpected NUL)");
|
||||
if (++bytesread >= YUV4MPEG_HEADER_MAXLEN)
|
||||
throw wxString(_T("ReadHeader: Malformed header (no terminating newline found)"));
|
||||
throw VideoOpenError("ReadHeader: Malformed header (no terminating newline found)");
|
||||
|
||||
// found a new tag
|
||||
if (buf == 0x20) {
|
||||
|
@ -220,14 +189,13 @@ std::vector<wxString> YUV4MPEGVideoProvider::ReadHeader(int64_t startpos, bool r
|
|||
return tags;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Parses a list of parameters and sets reader state accordingly
|
||||
/// @param tags The list of parameters to parse
|
||||
void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
||||
if (tags.size() <= 1)
|
||||
throw wxString(_T("ParseFileHeader: contentless header"));
|
||||
throw VideoOpenError("ParseFileHeader: contentless header");
|
||||
if (tags.front().Cmp(_T("YUV4MPEG2")))
|
||||
throw wxString(_T("ParseFileHeader: malformed header (bad magic)"));
|
||||
throw VideoOpenError("ParseFileHeader: malformed header (bad magic)");
|
||||
|
||||
// temporary stuff
|
||||
int t_w = -1;
|
||||
|
@ -244,17 +212,17 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
|||
|
||||
if (tags.at(i).StartsWith(_T("W"), &tag)) {
|
||||
if (!tag.ToLong(&tmp_long1))
|
||||
throw wxString(_T("ParseFileHeader: invalid width"));
|
||||
throw VideoOpenError("ParseFileHeader: invalid width");
|
||||
t_w = (int)tmp_long1;
|
||||
}
|
||||
else if (tags.at(i).StartsWith(_T("H"), &tag)) {
|
||||
if (!tag.ToLong(&tmp_long1))
|
||||
throw wxString(_T("ParseFileHeader: invalid height"));
|
||||
throw VideoOpenError("ParseFileHeader: invalid height");
|
||||
t_h = (int)tmp_long1;
|
||||
}
|
||||
else if (tags.at(i).StartsWith(_T("F"), &tag)) {
|
||||
if (!(tag.BeforeFirst(':')).ToLong(&tmp_long1) && tag.AfterFirst(':').ToLong(&tmp_long2))
|
||||
throw wxString(_T("ParseFileHeader: invalid framerate"));
|
||||
throw VideoOpenError("ParseFileHeader: invalid framerate");
|
||||
t_fps_num = (int)tmp_long1;
|
||||
t_fps_den = (int)tmp_long2;
|
||||
}
|
||||
|
@ -271,7 +239,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
|||
else if (!tag.CmpNoCase(_T("444alpha"))) t_pixfmt = Y4M_PIXFMT_444ALPHA;
|
||||
else if (!tag.CmpNoCase(_T("mono"))) t_pixfmt = Y4M_PIXFMT_MONO;
|
||||
else
|
||||
throw wxString(_T("ParseFileHeader: invalid or unknown colorspace"));
|
||||
throw VideoOpenError("ParseFileHeader: invalid or unknown colorspace");
|
||||
}
|
||||
else if (tags.at(i).StartsWith(_T("I"), &tag)) {
|
||||
if (!tag.CmpNoCase(_T("p"))) t_imode = Y4M_ILACE_PROGRESSIVE;
|
||||
|
@ -280,7 +248,7 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
|||
else if (!tag.CmpNoCase(_T("m"))) t_imode = Y4M_ILACE_MIXED;
|
||||
else if (!tag.CmpNoCase(_T("?"))) t_imode = Y4M_ILACE_UNKNOWN;
|
||||
else
|
||||
throw wxString(_T("ParseFileHeader: invalid or unknown interlacing mode"));
|
||||
throw VideoOpenError("ParseFileHeader: invalid or unknown interlacing mode");
|
||||
}
|
||||
else
|
||||
LOG_D("provider/video/yuv4mpeg") << "Unparsed tag: " << tags.at(i).c_str();
|
||||
|
@ -292,15 +260,15 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
|||
// but the "reference implementation" (mjpegtools) does, so I'm doing it too.
|
||||
if (inited) {
|
||||
if (t_w > 0 && t_w != w)
|
||||
throw wxString(_T("ParseFileHeader: illegal width change"));
|
||||
throw VideoOpenError("ParseFileHeader: illegal width change");
|
||||
if (t_h > 0 && t_h != h)
|
||||
throw wxString(_T("ParseFileHeader: illegal height change"));
|
||||
throw VideoOpenError("ParseFileHeader: illegal height change");
|
||||
if ((t_fps_num > 0 && t_fps_den > 0) && (t_fps_num != fps_rat.num || t_fps_den != fps_rat.den))
|
||||
throw wxString(_T("ParseFileHeader: illegal framerate change"));
|
||||
throw VideoOpenError("ParseFileHeader: illegal framerate change");
|
||||
if (t_pixfmt != Y4M_PIXFMT_NONE && t_pixfmt != pixfmt)
|
||||
throw wxString(_T("ParseFileHeader: illegal colorspace change"));
|
||||
throw VideoOpenError("ParseFileHeader: illegal colorspace change");
|
||||
if (t_imode != Y4M_ILACE_NOTSET && t_imode != imode)
|
||||
throw wxString(_T("ParseFileHeader: illegal interlacing mode change"));
|
||||
throw VideoOpenError("ParseFileHeader: illegal interlacing mode change");
|
||||
}
|
||||
else {
|
||||
w = t_w;
|
||||
|
@ -314,21 +282,19 @@ void YUV4MPEGVideoProvider::ParseFileHeader(const std::vector<wxString>& tags) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// @brief Parses a frame header
|
||||
/// @param tags The list of parameters to parse
|
||||
/// @return The flags set, as a binary mask
|
||||
/// This function is currently unimplemented (it will always return Y4M_FFLAG_NONE).
|
||||
YUV4MPEGVideoProvider::Y4M_FrameFlags YUV4MPEGVideoProvider::ParseFrameHeader(const std::vector<wxString>& tags) {
|
||||
if (tags.front().Cmp(_("FRAME")))
|
||||
throw wxString(_T("ParseFrameHeader: malformed frame header (bad magic)"));
|
||||
throw VideoOpenError("ParseFrameHeader: malformed frame header (bad magic)");
|
||||
|
||||
/// @todo implement parsing of frame flags
|
||||
|
||||
return Y4M_FFLAG_NONE;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Indexes the file
|
||||
/// @return The number of frames found in the file
|
||||
/// This function goes through the file, finds and parses all file and frame headers,
|
||||
|
@ -362,7 +328,7 @@ int YUV4MPEGVideoProvider::IndexFile() {
|
|||
seek_table.push_back(curpos);
|
||||
// seek to next frame header start position
|
||||
if (fseeko(sf, frame_sz, SEEK_CUR))
|
||||
throw wxString::Format(_T("IndexFile: failed seeking to position %d"), curpos + frame_sz);
|
||||
throw VideoOpenError(STD_STR(wxString::Format(_T("IndexFile: failed seeking to position %d"), curpos + frame_sz)));
|
||||
}
|
||||
else {
|
||||
/// @todo implement rff flags etc
|
||||
|
@ -372,8 +338,6 @@ int YUV4MPEGVideoProvider::IndexFile() {
|
|||
return framecount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @brief Gets a given frame
|
||||
/// @param n The frame number to return
|
||||
/// @return The video frame
|
||||
|
@ -398,7 +362,7 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) {
|
|||
src_fmt = FORMAT_YUY2; uv_width = w / 2; break;
|
||||
/// @todo add support for more pixel formats
|
||||
default:
|
||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: Unsupported source colorspace"));
|
||||
throw _T("YUV4MPEG video provider: GetFrame: Unsupported source colorspace");
|
||||
}
|
||||
|
||||
AegiVideoFrame tmp_frame;
|
||||
|
@ -416,11 +380,11 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) {
|
|||
size_t ret;
|
||||
ret = fread(tmp_frame.data[0], luma_sz, 1, sf);
|
||||
if (ret != 1 || feof(sf) || ferror(sf))
|
||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: failed to read luma plane"));
|
||||
throw _T("YUV4MPEG video provider: GetFrame: failed to read luma plane");
|
||||
for (int i = 1; i <= 2; i++) {
|
||||
ret = fread(tmp_frame.data[i], chroma_sz, 1, sf);
|
||||
if (ret != 1 || feof(sf) || ferror(sf))
|
||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: failed to read chroma planes"));
|
||||
throw _T("YUV4MPEG video provider: GetFrame: failed to read chroma planes");
|
||||
}
|
||||
|
||||
AegiVideoFrame dst_frame;
|
||||
|
|
|
@ -131,11 +131,6 @@ class YUV4MPEGVideoProvider : public VideoProvider {
|
|||
/// each frame header can be found
|
||||
std::vector<int64_t> seek_table;
|
||||
|
||||
wxString errmsg; /// error message
|
||||
|
||||
void LoadVideo(const wxString filename);
|
||||
void Close();
|
||||
|
||||
void CheckFileFormat();
|
||||
void ParseFileHeader(const std::vector<wxString>& tags);
|
||||
Y4M_FrameFlags ParseFrameHeader(const std::vector<wxString>& tags);
|
||||
|
|
|
@ -40,12 +40,6 @@
|
|||
#include <wx/glcanvas.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/GL.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "ass_override.h"
|
||||
|
|
|
@ -37,12 +37,8 @@
|
|||
#include <wx/toolbar.h>
|
||||
|
||||
#ifdef HAVE_APPLE_OPENGL_FRAMEWORK
|
||||
#include <OpenGL/GL.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include "gl/glext.h"
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue