summaryrefslogtreecommitdiffstats
path: root/src/encoder/encoder.cpp
blob: 7bbef1c4c0a5d54099363e992ca0c0abc6a02a87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/****************************************************************************
                   encoder.cpp  - encoder API for mixxx
                             -------------------
    copyright            : (C) 2009 by Phillip Whelan
    copyright            : (C) 2010 by Tobias Rafreider
    copyright            : (C) 2017 by Josep Maria Antolín
 ***************************************************************************/

#include "encoder/encoder.h"
#include "preferences/usersettings.h"
#include "recording/defs_recording.h"
// TODO(XXX): __FFMPEGFILE_ENCODERS__ is currently undefined because
// FFMPEG encoders provide less features than the other encoders and currently
// we don't have a good fallback for using them. That's why it's a bad idea
// to have the worse encoders to take precedence over the good ones.
#ifdef __FFMPEGFILE_ENCODERS__
#include "encoder/encoderffmpegmp3.h"
#include "encoder/encoderffmpegvorbis.h"
#else
#include "encoder/encodermp3.h"
#include "encoder/encodervorbis.h"
#endif
#include "encoder/encoderwave.h"
#include "encoder/encodersndfileflac.h"

#include "encoder/encodermp3settings.h"
#include "encoder/encodervorbissettings.h"
#include "encoder/encoderwavesettings.h"
#include "encoder/encoderflacsettings.h"

#ifdef __OPUS__
#include "encoder/encoderopus.h"
#endif
#include "encoder/encoderopussettings.h"

#include <QList>

EncoderFactory EncoderFactory::factory;

const EncoderFactory& EncoderFactory::getFactory()
{
    return factory;
}

EncoderFactory::EncoderFactory() {
    // Add new supported formats here. Also modify the getNewEncoder/getEncoderSettings method.
    m_formats.append(Encoder::Format("WAV PCM", ENCODING_WAVE, true));
    m_formats.append(Encoder::Format("AIFF PCM", ENCODING_AIFF, true));
    m_formats.append(Encoder::Format("FLAC", ENCODING_FLAC, true));
    m_formats.append(Encoder::Format("MP3", ENCODING_MP3, false));
    m_formats.append(Encoder::Format("OGG Vorbis", ENCODING_OGG, false));

#ifdef __OPUS__
    m_formats.append(Encoder::Format("Opus", ENCODING_OPUS, false));
#endif
}

const QList<Encoder::Format> EncoderFactory::getFormats() const
{
    return m_formats;
}

Encoder::Format EncoderFactory::getSelectedFormat(UserSettingsPointer pConfig) const
{
    return getFormatFor(pConfig->getValueString(ConfigKey(RECORDING_PREF_KEY, "Encoding")));
}
Encoder::Format EncoderFactory::getFormatFor(QString formatText) const
{
    for (const auto& format : m_formats) {
        if (format.internalName == formatText) {
            return format;
        }
    }
    qWarning() << "Format: " << formatText << " not recognized! Returning format "
        << m_formats.first().internalName;
    return m_formats.first();
}

EncoderPointer EncoderFactory::createRecordingEncoder(
        Encoder::Format format,
        UserSettingsPointer pConfig, 
        EncoderCallback* pCallback) const {
    EncoderRecordingSettingsPointer pSettings =
            getEncoderRecordingSettings(format, pConfig);
    return createEncoder(pSettings, pCallback);
}

EncoderPointer EncoderFactory::createEncoder(
        EncoderSettingsPointer pSettings,
        EncoderCallback* pCallback) const {
    EncoderPointer pEncoder;
    if (pSettings && pSettings->getFormat() == ENCODING_WAVE) {
        pEncoder = std::make_shared<EncoderWave>(pCallback);
        pEncoder->setEncoderSettings(*pSettings);
    } else if (pSettings && pSettings->getFormat() == ENCODING_AIFF) {
        pEncoder = std::make_shared<EncoderWave>(pCallback);
        pEncoder->setEncoderSettings(*pSettings);
    } else if (pSettings && pSettings->getFormat() == ENCODING_FLAC) {
        pEncoder = std::make_shared<EncoderSndfileFlac>(pCallback);
        pEncoder->setEncoderSettings(*pSettings);
    } else if (pSettings && pSettings->getFormat() == ENCODING_MP3) {
#ifdef __FFMPEGFILE_ENCODERS__
        pEncoder = std::make_shared<EncoderFfmpegMp3>(pCallback);
#else
        pEncoder = std::make_shared<EncoderMp3>(pCallback);
#endif
        pEncoder->setEncoderSettings(*pSettings);
    } else if (pSettings && pSettings->getFormat() == ENCODING_OGG) {
#ifdef __FFMPEGFILE_ENCODERS__
        pEncoder = std::make_shared<EncoderFfmpegVorbis>(pCallback);
#else
        pEncoder = std::make_shared<EncoderVorbis>(pCallback);
#endif
        pEncoder->setEncoderSettings(*pSettings);
    }
#ifdef __OPUS__
    else if (pSettings && pSettings->getFormat() == ENCODING_OPUS) {
        pEncoder = std::make_shared<EncoderOpus>(pCallback);
        pEncoder->setEncoderSettings(*pSettings);
    }
#endif
    else {
        qWarning() << "Unsupported format requested! "
                << QString(pSettings ? pSettings->getFormat() : QString("NULL"));
        DEBUG_ASSERT(false);
        pEncoder = std::make_shared<EncoderWave>(pCallback);;
    }
    return pEncoder;
}

EncoderRecordingSettingsPointer EncoderFactory::getEncoderRecordingSettings(Encoder::Format format,
    UserSettingsPointer pConfig) const
{
    if (format.internalName == ENCODING_WAVE) {
        return std::make_shared<EncoderWaveSettings>(pConfig, format.internalName);
    } else if (format.internalName == ENCODING_AIFF) {
        return std::make_shared<EncoderWaveSettings>(pConfig, format.internalName);
    } else if (format.internalName == ENCODING_FLAC) {
        return std::make_shared<EncoderFlacSettings>(pConfig);
    } else if (format.internalName == ENCODING_MP3) {
        return std::make_shared<EncoderMp3Settings>(pConfig);
    } else if (format.internalName == ENCODING_OGG) {
        return std::make_shared<EncoderVorbisSettings>(pConfig);
    } else if (format.internalName == ENCODING_OPUS) {
        return std::make_shared<EncoderOpusSettings>(pConfig);
    } else {
        qWarning() << "Unsupported format requested! " << format.internalName;
        DEBUG_ASSERT(false);
        return std::make_shared<EncoderWaveSettings>(pConfig, ENCODING_WAVE);
    }
}