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:
Thomas Goyne 2010-08-02 06:32:01 +00:00
parent 71fb04cd29
commit c10e9e3a5b
65 changed files with 574 additions and 1279 deletions

View file

@ -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
};

View file

@ -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

View file

@ -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

View file

@ -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.
};

View file

@ -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());
}

View file

@ -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) {

View file

@ -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; }

View file

@ -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);
}

View file

@ -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()

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>
}

View file

@ -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;

View file

@ -178,66 +178,69 @@ 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
provider = CreatePCMAudioProvider(filename);
if (provider) {
if (provider->GetBytesPerSample() == 2 && provider->GetSampleRate() >= 32000 && provider->GetChannels() == 1)
return provider;
else {
return CreateConvertAudioProvider(provider);
try {
provider = CreatePCMAudioProvider(filename);
}
catch (agi::FileNotFoundError const& err) {
msg = "PCM audio provider: " + err.GetMessage() + " not found.\n";
}
catch (AudioOpenError const& err) {
found = true;
msg += err.GetMessage();
}
}
if (!provider) {
std::vector<std::string> list = GetClasses(OPT_GET("Audio/Provider")->GetString());
if (list.empty()) throw AudioOpenError("No audio providers are available.");
for (unsigned int i=0;i<list.size();i++) {
try {
provider = Create(list[i], filename);
if (provider) break;
}
catch (agi::FileNotFoundError const& err) {
msg += list[i] + ": " + err.GetMessage() + " not found.\n";
}
catch (AudioOpenError const& err) {
found = true;
msg += list[i] + ": " + err.GetMessage();
}
}
}
// List of providers
std::vector<std::string> list = GetClasses(OPT_GET("Audio/Provider")->GetString());
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;
if (!provider) {
if (found) {
throw AudioOpenError(msg);
}
else {
throw agi::FileNotFoundError(STD_STR(filename));
}
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"); }
}
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;
}
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
///
void AudioProviderFactory::RegisterProviders() {

View file

@ -34,14 +34,10 @@
/// @ingroup audio_input
///
///////////
// Headers
#include "config.h"
#ifdef WITH_AVISYNTH
#ifndef AGI_PRE
#include <Mmreg.h>
#include <time.h>
@ -56,100 +52,59 @@
#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 {
// Include
if (filename.EndsWith(_T(".avs"))) {
wxFileName fn(filename);
char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal));
script = env->Invoke("Import", fname);
wxFileName fn(filename);
if (!fn.FileExists())
throw agi::FileNotFoundError(STD_STR(filename));
// Include
if (filename.EndsWith(_T(".avs"))) {
char *fname = env->SaveString(fn.GetShortPath().mb_str(csConvLocal));
script = env->Invoke("Import", fname);
}
// Use DirectShowSource
else {
const char * argnames[3] = { 0, "video", "audio" };
AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true };
// Load DirectShowSource.dll from app dir if it exists
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
if (dsspath.FileExists()) {
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetShortPath().mb_str(csConvLocal)));
}
// Use DirectShowSource
// Load audio with DSS if it exists
if (env->FunctionExists("DirectShowSource")) {
script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames);
}
// Otherwise fail
else {
wxFileName fn(filename);
const char * argnames[3] = { 0, "video", "audio" };
AVSValue args[3] = { env->SaveString(fn.GetShortPath().mb_str(csConvLocal)), false, true };
// Load DirectShowSource.dll from app dir if it exists
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
if (dsspath.FileExists()) {
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetShortPath().mb_str(csConvLocal)));
}
// Load audio with DSS if it exists
if (env->FunctionExists("DirectShowSource")) {
script = env->Invoke("DirectShowSource", AVSValue(args,3),argnames);
}
// 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));
}
LoadFromClip(script);
}
catch (AvisynthError &err) {
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

View file

@ -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);

View file

@ -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;
}

View file

@ -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(); }
};

View file

@ -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];
provider->GetAudio(tmp, start, count);
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;
}

View file

@ -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; }

View file

@ -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;
}
}

View file

@ -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);
};

View file

@ -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 */

View file

@ -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);
};

View file

@ -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 _T("");
return L"";
}

View file

@ -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);

View file

@ -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,9 +174,8 @@ 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
mapping_length = range_length;
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
if (mapping_start + (int64_t)mapping_length > file_size)
@ -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
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;
/// http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx
struct WaveFormatEx {
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t wBitsPerSample;
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;
}

View file

@ -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) {
}
}
}

View file

@ -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;

View file

@ -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

View file

@ -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 {

View file

@ -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

View file

@ -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); }

View file

@ -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);
Progress.ProgressDialog->Destroy();
if (Progress.IndexingCanceled) {
throw agi::UserCancelException("indexing cancelled by user");
}
if (Index == NULL) {
Progress.ProgressDialog->Destroy();
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

View file

@ -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 */

View file

@ -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;
@ -773,7 +780,7 @@ bool FrameMain::SaveSubtitles(bool saveas,bool withCharset) {
VideoContext::Get()->Stop();
wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString());
wxFileName origPath(ass->filename);
filename = wxFileSelector(_("Save subtitles file"),path,origPath.GetName() + _T(".ass"),_T("ass"),AssFile::GetWildcardList(1),wxFD_SAVE | wxFD_OVERWRITE_PROMPT,this);
filename = wxFileSelector(_("Save subtitles file"),path,origPath.GetName() + _T(".ass"),_T("ass"),AssFile::GetWildcardList(1),wxFD_SAVE | wxFD_OVERWRITE_PROMPT,this);
}
// Actually save

View file

@ -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

View file

@ -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");

View file

@ -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");

View file

@ -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) {
}
}

View file

@ -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;
};

View file

@ -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
///

View file

@ -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

View file

@ -41,10 +41,7 @@
#include <errno.h>
#include <algorithm>
#include <fstream>
#include <string>
#include <wx/string.h>
#endif
#include <libaegisub/io.h>

View file

@ -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);
}

View file

@ -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 {

View file

@ -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"

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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,174 +52,159 @@
#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;
AVSValue AvisynthVideoProvider::Open(wxFileName const& fname, wxString const& extension) {
char *videoFilename = env->SaveString(fname.GetShortPath().mb_str(csConvLocal));
usedDirectShow = false;
decoderName = _("Unknown");
// Avisynth file, just import it
if (extension == L".avs") {
LOG_I("avisynth/video") << "Opening .avs file with Import";
decoderName = L"Import";
return env->Invoke("Import", videoFilename);
}
wxString extension = _filename.Right(4);
extension.LowerCase();
try {
// Prepare filename
//char *videoFilename = env->SaveString(_filename.mb_str(wxConvLocal));
wxFileName fname(_filename);
char *videoFilename = env->SaveString(fname.GetShortPath().mb_str(csConvLocal));
// Avisynth file, just import it
if (extension == _T(".avs")) {
LOG_I("avisynth/video") << "Opening .avs file with Import";
script = env->Invoke("Import", videoFilename);
decoderName = _T("Import");
// Open avi file with AviSource
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 };
decoderName = L"AviSource";
return env->Invoke("AviSource", AVSValue(args,2), argnames);
}
// Open avi file with AviSource
else if (extension == _T(".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");
}
// 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) {
LOG_I("avisynth/video") << "Opening .d2v file with Mpeg2Dec3_Mpeg2Source";
script = env->Invoke("Mpeg2Dec3_Mpeg2Source", videoFilename);
decoderName = _T("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));
}
}
// If that fails, try opening it with DGDecode
else if (extension == _T(".d2v") && env->FunctionExists("DGDecode_Mpeg2Source")) {
LOG_I("avisynth/video") << "Opening .d2v file with DGDecode_Mpeg2Source";
script = env->Invoke("Mpeg2Source", videoFilename);
decoderName = _T("DGDecode_Mpeg2Source");
//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")) {
LOG_I("avisynth/video") << "Opening .d2v file with other Mpeg2Source";
script = env->Invoke("Mpeg2Source", videoFilename);
decoderName = _T("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);
}
// 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) {
wxFileName dss2path(StandardPaths::DecodePath(_T("?data/avss.dll")));
if (dss2path.FileExists()) {
env->Invoke("LoadPlugin",env->SaveString(dss2path.GetFullPath().mb_str(csConvLocal)));
}
}
// 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");
}
// Try DirectShowSource
if (!dss2) {
// Load DirectShowSource.dll from app dir if it exists
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
if (dsspath.FileExists()) {
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetFullPath().mb_str(csConvLocal)));
}
// Then try using DSS
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");
}
// 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");
}
}
// On Failure, fallback to DSS
catch (AvisynthError &) {
LOG_I("avisynth/video") << "Failed to open .avi file with AviSource, switching to DirectShowSource";
}
}
// Catch errors
catch (AvisynthError &err) {
LOG_E("avisynth/video") << "Avisynth error: " << err.msg;
throw _T("AviSynth error: ") + wxString(err.msg,csConvLocal);
// Open d2v with mpeg2dec3
if (extension == L".d2v" && env->FunctionExists("Mpeg2Dec3_Mpeg2Source")) {
LOG_I("avisynth/video") << "Opening .d2v file with 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
if (extension == L".d2v" && env->FunctionExists("DGDecode_Mpeg2Source")) {
LOG_I("avisynth/video") << "Opening .d2v file with 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
}
if (extension == L".d2v" && env->FunctionExists("Mpeg2Source")) {
LOG_I("avisynth/video") << "Opening .d2v file with other 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;
}
// Try loading DirectShowSource2
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)));
}
}
// If DSS2 loaded properly, try using it
if (env->FunctionExists("dss2")) {
LOG_I("avisynth/video") << "Opening file with DSS2";
decoderName = L"DSS2";
return env->Invoke("DSS2", videoFilename);
}
// Try DirectShowSource
// Load DirectShowSource.dll from app dir if it exists
wxFileName dsspath(StandardPaths::DecodePath(_T("?data/DirectShowSource.dll")));
if (dsspath.FileExists()) {
env->Invoke("LoadPlugin",env->SaveString(dsspath.GetFullPath().mb_str(csConvLocal)));
}
// Then try using DSS
if (env->FunctionExists("DirectShowSource")) {
const char *argnames[3] = { 0, "video", "audio" };
AVSValue args[3] = { videoFilename, true, false };
usedDirectShow = true;
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
LOG_E("avisynth/video") << "DSS function not found";
throw VideoNotSupported("No function suitable for opening the video found");
}
/// @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

View file

@ -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);

View file

@ -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(); }
};

View file

@ -122,12 +122,12 @@ DummyVideoProvider::DummyVideoProvider(wxString filename)
{
wxString params;
if (!filename.StartsWith(_T("?dummy:"), &params)) {
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();

View file

@ -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);

View file

@ -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();

View file

@ -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
if (provider->WantsCaching()) {
provider = new VideoProviderCache(provider);
}
return provider;
LOG_I("manager/video/provider") << list[i] << ": opened " << STD_STR(video);
if (provider->WantsCaching()) {
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;

View file

@ -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,36 +50,70 @@
#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;
fps_rat.num = -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;
wxString filename = wxFileName(fname).GetShortPath();
#ifdef WIN32
sf = _wfopen(filename.wc_str(), _T("rb"));
#else
sf = fopen(filename.utf8_str(), "rb");
#endif
if (sf == NULL) throw agi::FileNotFoundError(STD_STR(fname));
CheckFileFormat();
ParseFileHeader(ReadHeader(0, false));
if (w <= 0 || h <= 0)
throw VideoOpenError("Invalid resolution");
if (fps_rat.num <= 0 || fps_rat.den <= 0) {
fps_rat.num = 25;
fps_rat.den = 1;
LOG_D("provider/video/yuv4mpeg") << "framerate info unavailable, assuming 25fps";
}
if (pixfmt == Y4M_PIXFMT_NONE)
pixfmt = Y4M_PIXFMT_420JPEG;
if (imode == Y4M_ILACE_NOTSET)
imode = Y4M_ILACE_UNKNOWN;
luma_sz = w * h;
switch (pixfmt) {
case Y4M_PIXFMT_420JPEG:
case Y4M_PIXFMT_420MPEG2:
case Y4M_PIXFMT_420PALDV:
chroma_sz = (w * h) >> 2; break;
case Y4M_PIXFMT_422:
chroma_sz = (w * h) >> 1; break;
/// @todo add support for more pixel formats
default:
throw VideoOpenError("Unsupported pixel format");
}
frame_sz = luma_sz + chroma_sz*2;
num_frames = IndexFile();
if (num_frames <= 0 || seek_table.empty())
throw VideoOpenError("Unable to determine file length");
cur_fn = 0;
fseeko(sf, 0, SEEK_SET);
}
catch (...) {
Close();
if (sf) fclose(sf);
throw;
}
}
@ -86,88 +121,22 @@ YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(wxString filename) {
/// @brief Destructor
YUV4MPEGVideoProvider::~YUV4MPEGVideoProvider() {
Close();
if (sf) fclose(sf);
}
/// @brief Open a video file
/// @param _filename The video file to open
void YUV4MPEGVideoProvider::LoadVideo(const wxString _filename) {
Close();
wxString filename = wxFileName(_filename).GetShortPath();
#ifdef WIN32
sf = _wfopen(filename.wc_str(), _T("rb"));
#else
sf = fopen(filename.utf8_str(), "rb");
#endif
if (sf == NULL)
throw wxString::Format(_T("Failed to open file"));
CheckFileFormat();
ParseFileHeader(ReadHeader(0, false));
if (w <= 0 || h <= 0)
throw wxString(_T("Invalid resolution"));
if (fps_rat.num <= 0 || fps_rat.den <= 0) {
fps_rat.num = 25;
fps_rat.den = 1;
LOG_D("provider/video/yuv4mpeg") << "framerate info unavailable, assuming 25fps";
}
if (pixfmt == Y4M_PIXFMT_NONE)
pixfmt = Y4M_PIXFMT_420JPEG;
if (imode == Y4M_ILACE_NOTSET)
imode = Y4M_ILACE_UNKNOWN;
luma_sz = w * h;
switch (pixfmt) {
case Y4M_PIXFMT_420JPEG:
case Y4M_PIXFMT_420MPEG2:
case Y4M_PIXFMT_420PALDV:
chroma_sz = (w * h) >> 2; break;
case Y4M_PIXFMT_422:
chroma_sz = (w * h) >> 1; break;
/// @todo add support for more pixel formats
default:
throw wxString(_T("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"));
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;
}
/// @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("");
int bytesread = 0;
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;

View file

@ -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);

View file

@ -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"

View file

@ -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