Logo Search packages:      
Sourcecode: qmmp version File versions

outputjack.cpp

/***************************************************************************
 *   Copyright (C) 2007 by Zhuravlev Uriy                                  *
 *   stalkerg@gmail.com                                                    *
 *                                                                         *
 *   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 <QObject>
#include <QApplication>
#include <QtGlobal>
#include <QDir>
#include <QSettings>

#include "outputjack.h"
#include <qmmp/constants.h>
#include <qmmp/buffer.h>
#include <qmmp/visual.h>

#include <stdio.h>
#include <string.h>

void OutputJACK::stop()
{
    m_userStop = TRUE;
}

void OutputJACK::status()
{
    long ct = (m_totalWritten - latency()) / m_bps;

    if (ct < 0)
        ct = 0;

    if (ct > m_currentSeconds)
    {
        m_currentSeconds = ct;
        dispatch(m_currentSeconds, m_totalWritten, m_rate,
                 m_frequency, m_precision, m_channels);
    }
}

long OutputJACK::written()
{
    return m_totalWritten;
}

void OutputJACK::seek(long pos)
{
    /*recycler()->mutex()->lock ();
    recycler()->clear();
    recycler()->mutex()->unlock();*/

    m_totalWritten = (pos * m_bps);
    m_currentSeconds = -1;
}

OutputJACK::OutputJACK(QObject * parent, bool useVolume)
        : Output(parent), m_inited(FALSE), m_pause(FALSE), m_play(FALSE),
        m_userStop(FALSE), m_totalWritten(0), m_currentSeconds(-1),
        m_bps(-1), m_frequency(-1), m_channels(-1), m_precision(-1)
{
    JACK_Init();
}

OutputJACK::~OutputJACK()
{
    uninitialize();
}

void OutputJACK::configure(long freq, int chan, int prec, int brate)
{
    qDebug("OutputJACK: configure");
    m_precision = prec;
    m_channels = chan;
    m_frequency = freq;
    m_bps = freq * chan * (prec / 8);
    if(JACK_Open(&jack_device, prec, (unsigned long *)&freq, chan))
      {
        m_configure = FALSE;
      return;
      }
    else
        m_configure = TRUE;

    qDebug("OutputJACK: configure end");
}

void OutputJACK::pause()
{
    m_pause = (m_pause) ? FALSE : TRUE;
    {
        int state = m_pause ? OutputState::Paused: OutputState::Playing;
        dispatch(OutputState((OutputState::Type) state));
    }

}

bool OutputJACK::initialize()
{
    m_inited = m_pause = m_play = m_userStop = FALSE;
    m_currentSeconds = -1;
    m_totalWritten = 0;
    if (m_inited)
        m_inited = TRUE;
    m_inited = TRUE;
    m_configure = FALSE;
    jack_options_t options = JackNullOption;
    jack_status_t status;
    jack_client_t *client = jack_client_open ("test_qmmp", options, &status, NULL);
    if (client == NULL)
    {
        qDebug("jack_client_open() failed.");
        if (status & JackServerFailed)
        {
            qDebug("Unable to connect to JACK server.");
        }
    return FALSE;
    }
    jack_client_close (client);
    return TRUE;
}

long OutputJACK::latency()
{
    ulong used = 0;
    return used;
}

void OutputJACK::run()
{
    mutex()->lock ();
    if (! m_inited)
    {
        mutex()->unlock();
        return;
    }

    m_play = TRUE;
    Buffer *b = 0;
    bool done = FALSE;
    long m = 0;
    unsigned long l;

    dispatch(OutputState::Playing);

    mutex()->unlock();
    while (!done&&m_configure)
    {
        mutex()->lock ();
        recycler()->mutex()->lock ();
        done = m_userStop;

        while (! done && (recycler()->empty() || m_pause))
        {
            mutex()->unlock();
            recycler()->cond()->wakeOne();
            recycler()->cond()->wait(recycler()->mutex());
            mutex()->lock ();
            done = m_userStop;
            status();
        }

        if (! b)
        {
            b = recycler()->next();
            if (b->rate)
                m_rate = b->rate;
        }

        recycler()->cond()->wakeOne();
        recycler()->mutex()->unlock();

        if (b)
        {
            l = int(b->nbytes);
            unsigned char *buf = b->data;
            m_totalWritten += l;
            while (l > 0)
            {
                m = JACK_Write(jack_device, (unsigned char*)buf, l);
                if (!m)
                    usleep(2000);
                usleep(((m/m_channels)*100000)/m_frequency);
                l-=m;
                buf+=m;
            }

            status();
            dispatchVisual(b, m_totalWritten, m_channels, m_precision);
        }
        recycler()->mutex()->lock ();
        recycler()->done();
        recycler()->mutex()->unlock();
        b = 0;
        mutex()->unlock();
    }
    mutex()->lock ();
    m_play = FALSE;
    dispatch(OutputState::Stopped);
    mutex()->unlock();
}

void OutputJACK::uninitialize()
{
    if (!m_inited)
        return;
    m_inited = FALSE;
    m_inited = m_pause = m_play = m_userStop = FALSE;
    m_currentSeconds = -1;
    m_totalWritten = 0;
    if (m_configure)
        JACK_Close(jack_device);
    dispatch(OutputState::Stopped);
}


Generated by  Doxygen 1.6.0   Back to index