/*==============================================================================

FICHIER     : [avancement.c]

DATE        : 2006/01/0005 21:00:23

CREATEUR    : [Linux!jef]

COMMENTAIRE :
		Released under GPL license, see gnu.org
================================================================================

==============================================================================*/
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/stat.h>

#include <gnome.h>

#include "support.h"
#include "interface.h"
#include "systools.h"
#include "globals.h"
#include "const.h"
#include "uitools.h"
#include "mpeg2dec.h"

#define UI_STEP		0.001
#define UI_REFRESH_SEC	0.1

static GtkWidget * Wavancement;

typedef struct {
	int EstimatedSectors;
	long long ReadedBytes;
	double LastPct;
	struct timeval StartTime;
	struct timeval Time0;
	struct timeval lTv;
	long long totalSize;
	int totalSteps;
	int nbSteps;
} Progress_t;

static Progress_t Progress;
static Progress_t SaveProgress;

/*@$#[avancement.c] static proto. AutoProtoSigV1.1. date: 2009/02/04 23:14:52 */
#include "proto.h"
#ifdef __cplusplus
extern "C" {
#endif
/* avancement.c */
static void Time2HMS PROTO((double t, char *string));
static double DvdSpeed PROTO((long long rBytes, double elapsed));
#ifdef __cplusplus
}
#endif
/*@$% end of AutoProtoSigV1.1 (Dont remove this line) [-I ../include]*/


/*------------------------------------------------------------------------------
	PUSHAVANCEMENT-
Linux!jef 2006/01/23 22:14:19
------------------------------------------------------------------------------*/

void PushAvancement()
{
	SaveProgress = Progress;
}
/*------------------------------------------------------------------------------
	POPAVANCEMENT-
Linux!jef 2006/01/23 22:14:35
------------------------------------------------------------------------------*/

void PopAvancement()
{
	Progress = SaveProgress;
}

/*------------------------------------------------------------------------------
	INITAVANCEMENT-
Linux!jef 2005/12/28 22:34:20
------------------------------------------------------------------------------*/

void InitAvancement( int sectors )
{
	Progress.ReadedBytes = 0;
	Progress.EstimatedSectors = sectors;
	gettimeofday( &Progress.StartTime, NULL );
	Progress.LastPct = 0;
}
/*------------------------------------------------------------------------------
	CREATEAVANCEMENT-
Linux!jef 2006/01/05 21:02:56
------------------------------------------------------------------------------*/

void CreateAvancement( GtkWidget * forme )
{
	Wavancement = create_Avancement();
	gtk_window_set_transient_for( GTK_WINDOW(Wavancement), GTK_WINDOW(forme) );
	gtk_widget_show_now( Wavancement );
/* In case of no mpeg2 support */
#ifndef HAVE_LIBMPEG2
	{
		GtkWidget * item;

		item = lookup_widget(GTK_WIDGET(Wavancement), "mpeg2image" );
		g_assert( item );
		gtk_widget_hide( item );
		item = lookup_widget(GTK_WIDGET(Wavancement), "visumpeg" );
		g_assert( item );
		gtk_widget_hide( item );
	}
#endif
	gettimeofday( &Progress.Time0, NULL );
	Progress.totalSteps = 0;
	Progress.nbSteps = 0;
	UserStopF = 0;
	UserPauseF = 0;
}
/***************************************************************************//**
 *	HIDEMPEGVISU-
 * @date	2009/01/28 21:29:05
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

void HideMpegVisu()
{
	GtkWidget * item;

	item = lookup_widget(GTK_WIDGET(Wavancement), "mpeg2image" );
	g_assert( item );
	gtk_widget_hide( item );
	item = lookup_widget(GTK_WIDGET(Wavancement), "visumpeg" );
	g_assert( item );
	gtk_widget_hide( item );
}


/*------------------------------------------------------------------------------
	DESTROYAVANCEMENT-
Linux!jef 2006/01/05 21:03:15
------------------------------------------------------------------------------*/

void DestroyAvancement()
{
	gtk_widget_destroy(GTK_WIDGET(Wavancement));
}
/*------------------------------------------------------------------------------
	AVANCEMENT-
Linux!jef 2005/12/07 01:15:50
------------------------------------------------------------------------------*/

int Avancement( lenReaded )
int  lenReaded;
{
	Progress.ReadedBytes += lenReaded;

	return( 0 );
}
/*------------------------------------------------------------------------------
	AVANCEMENTABS-
Linux!jef 2005/12/07 01:15:50
------------------------------------------------------------------------------*/

int AvancementAbs( pos )
long pos;
{
	Progress.ReadedBytes = pos;

	return( 0 );
}
/*------------------------------------------------------------------------------
	SETTOTALSIZE-
Linux!jef 2006/01/25 22:07:22
------------------------------------------------------------------------------*/

void SetTotalSize( long long tSize )
{
	Progress.totalSize = tSize;
}
/*------------------------------------------------------------------------------
	SETTOTALSTEPS-
Linux!jef 2006/01/31 22:27:09
------------------------------------------------------------------------------*/

void SetTotalSteps( int steps )
{
	Progress.totalSteps = steps;
}
/*------------------------------------------------------------------------------
	NEWSTEP-
Linux!jef 2006/01/31 22:27:31
------------------------------------------------------------------------------*/

void NewStep()
{
	double pct;
	GtkWidget * item;

	Progress.nbSteps++;
	if( Progress.totalSteps ) {
		pct = (double)Progress.nbSteps / (double)Progress.totalSteps;
		if( pct > 1.0 ) pct = 1;
		item = lookup_widget(GTK_WIDGET(Wavancement), "totalprogress" );
		g_assert( item );
		gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(item), pct );
		gtk_widget_show_now( item );
		GtkFlush();
	}
}

/*------------------------------------------------------------------------------
	TIME2HMS-
Linux!jef 2005/12/15 23:31:07
------------------------------------------------------------------------------*/

static void Time2HMS( double t, char * string )
{
	int h,m,s;

	h = (t / 3600 );
	t -= ( h * 3600 );
	m = ( t / 60 );
	t -= (m * 60 );
	s = t;
	sprintf( string,"%2.2d:%2.2d:%2.2d", h, m, s );
}
/*------------------------------------------------------------------------------
	DVDSPEED-
Linux!jef 2006/02/14 21:45:18
------------------------------------------------------------------------------*/

static double DvdSpeed( long long rBytes, double elapsed )
{
	double res = rBytes / (1.321 * 1024 * 1024 );

	if( !elapsed )	return( 1.0 );
	return( res / elapsed );
}

/*------------------------------------------------------------------------------
	AVANCEMENTUI-
Linux!jef 2005/12/09 21:21:13
------------------------------------------------------------------------------*/

int AvancementUi()
{
	long long secReaded;
	double pctg, pcts;
	int refreshF = 0;
	struct timeval tv;
	double delta;
	char message[200];
	GtkWidget * item;

//fprintf(stderr,"gdk_threads_enter:>\n");
//	gdk_threads_enter();

	secReaded = Progress.ReadedBytes / (long long)SECTOR_SIZE;
	pcts = (double)secReaded / (double)Progress.EstimatedSectors;
	if( pcts > 1.0 ) pcts = 1;
	gettimeofday( &tv, NULL );

	delta = tv.tv_sec - Progress.lTv.tv_sec;
	delta += ((double)( tv.tv_usec - Progress.lTv.tv_usec )) / 1000000.0;
	if( delta < UI_REFRESH_SEC  )	goto next;

	if( MyAbs( pcts - Progress.LastPct ) >= UI_STEP ) {
		double totalTime;
		double elapsedTime;
		double remainTime;
		char totalStr[100];
		char elapsedStr[100];
		char remainStr[100];


		pctg = (double)Progress.nbSteps / (double)Progress.totalSteps;
		if( pctg > 1.0 ) pctg = 1;

		totalTime = tv.tv_sec - Progress.Time0.tv_sec;
		totalTime += (double)(tv.tv_usec - Progress.Time0.tv_usec) / 1000000.0;
		elapsedTime = tv.tv_sec - Progress.StartTime.tv_sec;
		elapsedTime += (double)(tv.tv_usec - Progress.StartTime.tv_usec) / 1000000.0;
		remainTime = (elapsedTime / pcts) - elapsedTime;
		Time2HMS( totalTime, totalStr );
		Time2HMS( elapsedTime, elapsedStr );
		Time2HMS( remainTime, remainStr );


		item = lookup_widget(GTK_WIDGET(Wavancement), "totalprogress" );
		g_assert( item );
// fprintf(stderr,"AvancementUI: %p(%f)\n", item, pct );
		gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(item), pctg );
		sprintf( message,_("Total %d%% a %.2fx"),
			(int)(pctg * 100.0),
			DvdSpeed( Progress.ReadedBytes, elapsedTime ) );
		gtk_progress_bar_set_text( GTK_PROGRESS_BAR(item), message );
		gtk_widget_show_now( item );


		item = lookup_widget(GTK_WIDGET(Wavancement), "streamprogress" );
		g_assert( item );
// fprintf(stderr,"AvancementUI: %p(%f)\n", item, pct );
		gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(item), pcts);
		sprintf( message,_("%d%% (%s restant)"), (int)(pcts * 100.0), remainStr );
		gtk_progress_bar_set_text( GTK_PROGRESS_BAR(item), message );
		gtk_widget_show_now( item );

		Progress.LastPct = pcts;
		refreshF = 1;
	}
	refreshF = 1;
	Progress.lTv = tv;

next:;
	if( ImageReadyF ) {
		item = lookup_widget(GTK_WIDGET(Wavancement), "mpeg2image" );
		g_assert( item );
	  	gtk_image_set_from_file( GTK_IMAGE( item ), PPM_FILE );
	  	unlink( PPM_FILE );
	  	ImageReadyF = 0;
	}
	if( refreshF ) {
		GtkFlush();
	}
//fprintf(stderr,"gdk_threads_leave:>\n");
//	gdk_threads_leave();

	if( UserStopF )	return( -1 );
	while( UserPauseF ) {
		GtkFlush();
		if( UserStopF )	return( -1 );
		usleep( 10000 );
	}
	return( 0 );
}
/*------------------------------------------------------------------------------
	AVANCEMENTUI2-
Linux!jef 2006/01/05 21:09:22
------------------------------------------------------------------------------*/

int AvancementUi2( double pcts )
{
	if( MyAbs( pcts - Progress.LastPct ) >= UI_STEP ) {
		GtkWidget * item;
		struct timeval tv;
		double pctg;
		double totalTime;
		double elapsedTime;
		double remainTime;
		char totalStr[100];
		char elapsedStr[100];
		char remainStr[100];
		char message[200];

		item = lookup_widget(GTK_WIDGET(Wavancement), "streamprogress" );
		g_assert(item);
// fprintf(stderr,"AvancementUI: %p(%f)\n", item, pcts );
		gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(item), pcts );

		gettimeofday( &tv, NULL );

		totalTime = tv.tv_sec - Progress.Time0.tv_sec;
		totalTime += (double)(tv.tv_usec - Progress.Time0.tv_usec) / 1000000.0;
		elapsedTime = tv.tv_sec - Progress.StartTime.tv_sec;
		elapsedTime += (double)(tv.tv_usec - Progress.StartTime.tv_usec) / 1000000.0;
		remainTime = (elapsedTime / pcts) - elapsedTime;
		Time2HMS( totalTime, totalStr );
		Time2HMS( elapsedTime, elapsedStr );
		Time2HMS( remainTime, remainStr );

		sprintf( message,_("%d%% (%s restant)"), (int)(pcts * 100.0), remainStr );
		gtk_progress_bar_set_text( GTK_PROGRESS_BAR(item), message );
		gtk_widget_show_now( item );

		pctg = (double)Progress.nbSteps / (double)Progress.totalSteps;
		if( pctg > 1.0 ) pctg = 1;
		item = lookup_widget(GTK_WIDGET(Wavancement), "totalprogress" );
		g_assert( item );
// fprintf(stderr,"AvancementUI: %p(%f)\n", item, pct );
		gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(item), pctg );
		sprintf( message,_("Total %d%% a %.2fx"),
			(int)(pctg * 100.0),
			DvdSpeed( Progress.ReadedBytes, elapsedTime ) );
		gtk_progress_bar_set_text( GTK_PROGRESS_BAR(item), message );
		gtk_widget_show_now( item );


		Progress.LastPct = pcts;
		GtkFlush();
	}
	if( UserStopF )	return( -1 );
	return( 0 );
}

/*------------------------------------------------------------------------------
	DISPLAYAVANCEMENT-
Linux!jef 2005/12/15 22:47:14
------------------------------------------------------------------------------*/

void DisplayAvancement( char * format, ... )
{
	char string[4096];
	va_list args;
	GtkWidget * item;
	GtkTextBuffer * textBuffer;
	GtkTextIter iter;

	va_start( args, format );
	vsnprintf( string, sizeof(string), format, args );

	item = lookup_widget(GTK_WIDGET(Wavancement), "textview1" );
	if( !item )	return;
	textBuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(item) );
	if( !textBuffer )	return;
	gtk_text_buffer_insert_at_cursor ( textBuffer, string, strlen( string ));

	gtk_text_buffer_get_end_iter( textBuffer, &iter );
	gtk_text_view_scroll_to_iter(	GTK_TEXT_VIEW(item),
					&iter,
					0.0,
					TRUE,
					0.0,
					1.0 );
	gtk_widget_show_now( item );
	GtkFlush();
	va_end( args );
}
/*------------------------------------------------------------------------------
	TOTALTIME-
Linux!jef 2006/03/01 21:05:27
------------------------------------------------------------------------------*/

void TotalTime( char * string )
{
	struct timeval tv;
	double totalTime;

	gettimeofday( &tv, NULL );

	totalTime = tv.tv_sec - Progress.Time0.tv_sec;
	totalTime += (double)(tv.tv_usec - Progress.Time0.tv_usec) / 1000000.0;
	Time2HMS( totalTime, string );
}
/***************************************************************************//**
 *	RESETUSERSTOP-
 * @date	2009/01/20 22:00:08
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

void ResetUserStop()
{
	UserStopF = 0;
}
/***************************************************************************//**
 *	ISUSERSTOP-
 * @date	2009/01/20 22:00:52
 * @author	jef-Linux
 * @brief
 *	Pas d'explication
 * @details
 *	Pas de details
 * @param[in]	Pas de detail
 * @param[out]	Pas de detail
*******************************************************************************/

int IsUserStop()
{
	return( UserStopF );
}

