aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Input/sndfile/decoder_sndfile.h
blob: 9a66acd3d99ca62e96b194a280218fceab4161b5 (plain) (blame)
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
/***************************************************************************
 *   Copyright (C) 2007-2008 by Ilya Kotov                                 *
 *   forkotov02@hotmail.ru                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef DECODER_AUDIOFILE_H
#define DECODER_AUDIOFILE_H

extern "C"{
#include <sndfile.h>
}
#include <qmmp/decoder.h>


class DecoderSndFile : public Decoder
{
public:
    DecoderSndFile(QObject *, DecoderFactory *, QIODevice *, Output *);
    virtual ~DecoderSndFile();

    // Standard Decoder API
    bool initialize();
    double lengthInSeconds();
    void seek(double);
    void stop();


private:
    // thread run function
    void run();
    // helper functions
    void flush(bool = FALSE);
    void deinit();

    // output buffer
    char *m_output_buf;

    SNDFILE *m_sndfile;
    ulong m_output_bytes, m_output_at;
    //struct sndfile_data *m_data;
    short *m_buf;
    unsigned int bks;
    bool m_done, m_finish, m_inited, m_user_stop;
    long m_freq, m_bitrate;
    int m_chan;
    unsigned long m_output_size;
    double m_totalTime, m_seekTime;
};


#endif // DECODER_SNDFILE_H
50' href='#n250'>250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
/***************************************************************************
 *   Copyright (C) 2006 by Ilya Kotov                                      *
 *   forkotov02@hotmail.ru                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <QIODevice>
#include <QFile>
#include <QApplication>

#include "decoderfactory.h"
#include "constants.h"
#include "streamreader.h"

#include "soundcore.h"

SoundCore::SoundCore(QObject *parent)
        : QObject(parent)
{
    m_decoder = 0;
    m_output = 0;
    m_input = 0;
    m_paused = FALSE;
    m_useEQ = FALSE;
    m_update = FALSE;
    m_preamp = 0;
    m_vis = 0;
    for (int i = 1; i < 10; ++i)
        m_bands[i] = 0;
    m_error = NoError;
    m_output = Output::create(this);
    if (!m_output)
    {
        m_error = DecoderError;
        qWarning("SoundCore: unable to create output");
    }
    connect(m_output, SIGNAL(stateChanged(const OutputState&)),
            SIGNAL(outputStateChanged(const OutputState&)));

    QList<OutputFactory*> *outputFactories = Output::outputFactories();
    foreach(OutputFactory* of, *outputFactories)
        qApp->installTranslator(of->createTranslator(this));

    QList<DecoderFactory*> *decoderFactories = Decoder::decoderFactories();
    foreach(DecoderFactory* df, *decoderFactories)
        qApp->installTranslator(df->createTranslator(this));
}


SoundCore::~SoundCore()
{}

bool SoundCore::play(const QString &source)
{
    stop();
    if (source.isEmpty())
    {
        m_error = DecoderError;
        return FALSE;
    }
    if(source.left(4) == "http")
    {
        m_input = new StreamReader(source, this);
    }
    else
        m_input = new QFile(source);

    m_error = OutputError;
    if (!m_output)
    {
        m_output = Output::create(this);
        if (!m_output)
        {
            qWarning("SoundCore: unable to create output");
            return FALSE;
        }
        connect(m_output, SIGNAL(stateChanged(const OutputState&)),
                SIGNAL(outputStateChanged(const OutputState&)));
    }
    if (! m_output->initialize())
        return FALSE;

    m_error = DecoderError;

    if(m_vis)
    {
        m_vis->setOutput(m_output);
        m_output->addVisual(m_vis);
    }

    if (! m_decoder)
    {
        qDebug ("SoundCore: creating decoder");
        m_decoder = Decoder::create(this, source, m_input, m_output);

        if (! m_decoder)
        {
            qWarning("SoundCore: unsupported fileformat");
            stop();
            emit decoderStateChanged(DecoderState(DecoderState::Error));
            return FALSE;
        }
        qDebug ("ok");
        m_decoder->setBlockSize(globalBlockSize);
        connect(m_decoder, SIGNAL(stateChanged(const DecoderState&)),
                SIGNAL(decoderStateChanged(const DecoderState&)));
        setEQ(m_bands, m_preamp);
        setEQEnabled(m_useEQ);
    }
    qDebug("Decoder create OK");

    if (m_decoder->initialize())
    {
        m_output->start();
        m_decoder->start();
        m_error = NoError;
        return TRUE;
    }
    stop();
    return FALSE;
}

uint SoundCore::error()
{
    return m_error;
}

void SoundCore::stop()
{
    m_paused = FALSE;
    if (m_decoder && m_decoder->isRunning())
    {
        m_decoder->mutex()->lock ();
        m_decoder->stop();
        m_decoder->mutex()->unlock();
    }

    if (m_output)
    {
        m_output->mutex()->lock ();
        m_output->stop();
        m_output->mutex()->unlock();
    }

    // wake up threads
    if (m_decoder)
    {
        m_decoder->mutex()->lock ();
        m_decoder->cond()->wakeAll();
        m_decoder->mutex()->unlock();
    }

    if (m_output)
    {
        m_output->recycler()->mutex()->lock ();
        m_output->recycler()->cond()->wakeAll();
        m_output->recycler()->mutex()->unlock();
    }

    if (m_decoder)
        m_decoder->wait();

    if (m_output)
        m_output->wait();

    if (m_output && m_output->isInitialized())
    {
        m_output->uninitialize();
    }
    
    //display->setTime(0);
    if (m_decoder)
    {
        delete m_decoder;
        m_decoder = 0;
    }
    if (m_input)
    {
        delete m_input;
        m_input = 0;
    }
    // recreate output
    if (m_update && m_output)
    {
        delete m_output;
        m_output = 0;
        m_update = FALSE;
        m_output = Output::create(this);
        if (!m_output)
        {
            qWarning("SoundCore: unable to create output");
        }
        connect(m_output, SIGNAL(stateChanged(const OutputState&)),
                SIGNAL(outputStateChanged(const OutputState&)));
    }
}

void SoundCore::pause()
{
    if (m_output)
    {
        m_output->mutex()->lock ();
        m_output->pause();
        m_output->mutex()->unlock();
    }

    // wake up threads
    if (m_decoder)
    {
        m_paused = !m_paused;
        m_decoder->mutex()->lock ();
        m_decoder->cond()->wakeAll();
        m_decoder->mutex()->unlock();
    }

    if (m_output)
    {
        m_output->recycler()->mutex()->lock ();
        m_output->recycler()->cond()->wakeAll();
        m_output->recycler()->mutex()->unlock();
    }
}

void SoundCore::seek(int pos)
{
    if (m_output && m_output->isRunning())
    {
        m_output->mutex()->lock ();
        m_output->seek(pos);

        if (m_decoder && m_decoder->isRunning())
        {
            m_decoder->mutex()->lock ();
            m_decoder->seek(pos);
            m_decoder->mutex()->unlock();
        }

        m_output->mutex()->unlock();
    }
}

int SoundCore::length()
{
    if (m_decoder)
        return int(m_decoder->lengthInSeconds());
    return 0;
}

bool SoundCore::isInitialized()
{
    if (m_decoder)
        return TRUE;
    return FALSE;
}

bool SoundCore::isPaused()
{
    return m_paused;
}

void SoundCore::setEQ(int bands[10], const int &preamp)
{
    for (int i = 0; i < 10; ++i)
        m_bands[i] = bands[i];
    m_preamp = preamp;
    if (m_decoder)
    {
        m_decoder->mutex()->lock ();
        m_decoder->setEQ(m_bands, m_preamp);
        m_decoder->setEQEnabled(m_useEQ);
        m_decoder->mutex()->unlock();
    }
}

void SoundCore::setEQEnabled(bool on)
{
    m_useEQ = on;
    if (m_decoder)
    {
        m_decoder->mutex()->lock ();
        m_decoder->setEQ(m_bands, m_preamp);
        m_decoder->setEQEnabled(on);
        m_decoder->mutex()->unlock();
    }
}

void SoundCore::setVolume(int L, int R)
{
    if (m_output)
        m_output->setVolume(L,R);
}

void SoundCore::updateConfig()
{
    m_update = TRUE;
    if (isInitialized())
        return;
    stop();
}

void SoundCore::addVisualization(Visualization *visual)
{
    m_vis = visual;
}