/***************************************************************************
 *   Copyright (C) 2004-2005 by Jürgen Kofler                              *
 *   kaffeine@gmx.net                                                      *
 *                                                                         *
 *   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.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.           *
 ***************************************************************************/

/*
 *  Heavily based on kiss by Ronald Bultje <rbultje@ronald.bitfreak.net>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <klocale.h>
#include <kdebug.h>

#include <qslider.h>
#include <qlabel.h>
#include <qtimer.h>

#include "timer.h"

#include "timer.moc"


Timer::Timer(GstElement *_play) : QObject()
{
	m_label = new QLabel("0:00 / 0:00", 0);
	m_slider = new QSlider(Qt::Horizontal, 0);
	m_slider->setMinValue(0);

	m_timer = new QTimer(this);
	connect(m_timer, SIGNAL(timeout()), SLOT(slotUpdate()));

	gst_object_ref(GST_OBJECT(_play));
	m_play = _play;
	g_signal_connect(m_play, "state-change", G_CALLBACK (cb_state), this);

	m_pos = GST_CLOCK_TIME_NONE;
	m_len = GST_CLOCK_TIME_NONE;

	connect(m_slider, SIGNAL(sliderPressed()), this, SLOT(slotStartseek()));
	connect(m_slider, SIGNAL(sliderReleased()), this, SLOT(slotEndseek()));
	connect(m_slider, SIGNAL(sliderMoved(int)), this, SLOT(slotSeek(int)));
	m_seeking = false;
}

Timer::~Timer()
{
	gst_object_unref(GST_OBJECT(m_play));
	kdDebug() << "Timer: destructed" << endl;
}

void Timer::slotStartseek()
{
	m_seeking = true;
}

void Timer::slotEndseek()
{
	m_seeking = false;

	/* do actual seek */
	gint64 val = m_slider->value ();
	gst_element_seek (m_play, (GstSeekType) (GST_SEEK_METHOD_SET |
	                  GST_FORMAT_TIME | GST_SEEK_FLAG_FLUSH),
	                  val * GST_SECOND);
}

static char *niceTime(guint64 t)
{
	if (t >= GST_SECOND * 60 * 60)
	{
		return g_strdup_printf ("%d:%02d:%02d",
		                        (int) (t / (GST_SECOND * 60 * 60)),
		                        (int) ((t / (GST_SECOND * 60)) % 60),
		                        (int) ((t / GST_SECOND) % 60));
	}
	else
	{
		return g_strdup_printf ("%d:%02d",
		                        (int) ((t / (GST_SECOND * 60)) % 60),
		                        (int) ((t / GST_SECOND) % 60));
	}
}

void Timer::slotSeek(int val)
{
	gchar *txt, *txt2;

	txt = niceTime (val * GST_SECOND);
	txt2 = g_strdup_printf(i18n("Seeking to %s").ascii(), txt);
	g_free (txt);
	m_label->setText (txt2);
	g_free (txt2);
}

void Timer::seekPercent(uint percent)
{
	slotStartseek();
	slotSeek((m_slider->maxValue() * percent) / 100);
	slotEndseek();
}

void Timer::slotUpdate(void)
{
	gint64 t;
	GstFormat fmt = GST_FORMAT_TIME;
	gboolean m_len_change = FALSE, m_pos_change = FALSE;
	char *txt;

	if (m_seeking)
		return;

	/* get media m_length if not yet known */
	if (!GST_CLOCK_TIME_IS_VALID (m_len))
	{
		if (gst_element_query (m_play, GST_QUERY_TOTAL, &fmt, &t))
		{
			m_len = t;
			m_len_change = TRUE;
			m_slider->setMaxValue (m_len / GST_SECOND);
		}
	}

	/* get m_position in the media now */
	if (!gst_element_query (m_play, GST_QUERY_POSITION, &fmt, &t))
		return;

	if (!GST_CLOCK_TIME_IS_VALID (m_pos) || (int) (m_pos / GST_SECOND) != (int) (t / GST_SECOND))
	{
		m_pos_change = TRUE;
	}
	m_pos = t;

	m_currentTimeMS = m_pos/1000000;
	m_totalTimeMS = m_len/1000000;

	/* let's write it down */
	if (m_pos_change || m_len_change)
	{
		if (GST_CLOCK_TIME_IS_VALID (m_len))
		{
			gchar *t1 = niceTime (m_pos), *t2 = niceTime (m_len);

			txt = g_strdup_printf ("%s / %s", t1, t2);
			g_free (t1);
			g_free (t2);
		}
		else
		{
			txt = niceTime (m_pos);
		}
		m_label->setText (txt);
		g_free (txt);
	}

	m_slider->setValue (m_pos / GST_SECOND);
}

void Timer::newState(GstElementState old_state, GstElementState new_state)
{
	if (old_state <= GST_STATE_PAUSED && new_state >= GST_STATE_PLAYING)
	{
		m_timer->start (100);
	}
	else
		if (new_state <= GST_STATE_PAUSED && old_state >= GST_STATE_PLAYING)
		{
			m_timer->stop ();
		}
		else
			if (new_state <= GST_STATE_READY && old_state >= GST_STATE_PAUSED)
			{
				m_pos = GST_CLOCK_TIME_NONE;
				m_len = GST_CLOCK_TIME_NONE;

				m_slider->setValue (0);
				m_label->setText("0:00 / 0:00");
			}
}

QLabel* Timer::getLabel() const
{
	return m_label;
}

QSlider* Timer::getSlider() const
{
	return m_slider;
}

/************ CALLBACKS ****************/

void Timer::cb_state(GstElement* /*play*/, GstElementState old_state, GstElementState new_state, gpointer data)
{
	((Timer*)data)->newState(old_state, new_state);
}


