#
#	$Id: Information.pm,v 1.44 2004/12/30 03:10:14 kevin Exp $
#
#	Author: Kevin Walsh <kevin@cursor.biz>
#
#	Copyright (c) 2003-2004 Cursor Software Limited.
#	All rights reserved.
#
#	The French translation text was kindly supplied by Nicolas Guillemain.
#
#	----------------------------------------------------------------------
#
#	SlimServer, player library and module information.
#
#	Displays various bits of information relating to the SlimServer,
#	the current player, the music library and the installed plug-in
#	modules.
#
#	Scroll through the information items using the up/down buttons.
#	If you see a "->" symbol then you may press RIGHT to move into
#	a sub-menu.  Press LEFT to move out of a sub-menu.
#
#	----------------------------------------------------------------------
#
#	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
#
package Plugins::Information;
use POSIX qw(strftime);
use File::Spec::Functions qw(catfile);
use Slim::Utils::Strings qw(string);
use strict;

use vars qw($VERSION);
$VERSION = substr(q$Revision: 1.44 $,10);

my @main_list = qw(
    library
    player
    server
    module
);

my @library_list = (
    [ 'TIME',        'time',   0, \&Slim::Music::Info::total_time ],
    [ 'ALBUMS',      'int',    0, sub { Slim::Music::Info::albumCount([],[],[],[]) } ],
    [ 'TRACKS',      'int',    0, sub { Slim::Music::Info::songCount([],[],[],[]) } ],
    [ 'ARTISTS',     'int',    0, sub { Slim::Music::Info::artistCount([],[],[],[]) } ],
    [ 'GENRES',      'int',    0, sub { Slim::Music::Info::genreCount([],[],[],[]) } ],
);

my @player_list = (
    [ 'NAME',        'string', 1, sub { Slim::Utils::Prefs::clientGet(shift,'playername') } ],
    [ 'MODEL',       'string', 1, sub { uc(shift->model) } ],
    [ 'IP_ADDRESS',  'string', 1, sub { shift->ip } ],
    [ 'PORT_NUMBER', 'string', 1, sub { my $client = shift; $client->port . ' (' . ($client->tcpsock ? 'TCP' : 'UDP') . ')' } ],
    [ 'MAC_ADDRESS', 'string', 1, sub { uc(shift->macaddress) } ],
    [ 'FIRMWARE',    'string', 1, sub { shift->revision } ],
    [ 'UPGRADE',     'string', 1, sub { string('PLUGIN_INFORMATION_' . (shift->needsUpgrade ? 'YES' : 'NO')) } ],
    [ 'VFD_MODEL',   'string', 1, sub { uc(shift->vfdmodel) } ],
    [ 'SIGNAL',      'string', 1, sub { my $s = shift->signalStrength; defined($s) ? $s : string('PLUGIN_INFORMATION_NA') } ],
    [ 'BUFFER',      'string', 1, sub { player_buffer(shift)} ],
);

my @server_list = (
    [ 'VERSION',     'string', 0, sub { $::VERSION } ],
    [ 'STREAM_PORT', 'string', 0, sub { 3483 } ],
    [ 'HTTP_PORT',   'string', 0, sub { Slim::Utils::Prefs::get('httpport') } ],
    [ 'CLIENTS',     'int',    1, \&Slim::Player::Client::clientCount ],
);

my @module_list;

my %menu = (
    main => {
	lines => \&main_lines,
	list => \@main_list,
    },
    library => {
	lines => \&info_lines,
	list => \@library_list,
    },
    player => {
	lines => \&info_lines,
	list => \@player_list,
    },
    server => {
	lines => \&info_lines,
	list => \@server_list,
    },
    module => {
	lines => \&module_lines,
	list => \@module_list,
    },
);

my %format = (
    'int' => sub {
	Slim::Utils::Misc::delimitThousands(shift);
    },
    'time' => sub {
	my $time = shift || 0;

	sprintf(
	    "%d:%02d:%02d",
	    ($time / 3600),
	    ($time / 60) % 60,
	    $time % 60,
	);
    },
    'string' => sub {
	shift;
    },
);

my $modes_set;
my $modules;
my %enabled;
my %context;

my %functions = (
    'left' => sub {
	my $client = shift;

	Slim::Buttons::Common::popModeRight($client);
    },
    'right' => sub {
	my $client = shift;
	my $nextmode = find_nextmode($client);

	if ($nextmode && ref($menu{$nextmode}->{list})) {
	    Slim::Buttons::Common::pushModeLeft(
		$client,
		"plugins-information-$nextmode",
	    );
	}
	else {
	    Slim::Display::Animation::bumpRight($client);
	}
    },
    'up' => sub {
	my $client = shift;
	my $ref = $context{$client};

	$ref->{$ref->{current}} = Slim::Buttons::Common::scroll(
	    $client,
	    -1,
	    ($#{$ref->{list}} + 1),
	    $ref->{$ref->{current}},
	);
	$client->update();
    },
    'down' => sub {
	my $client = shift;
	my $ref = $context{$client};

	$ref->{$ref->{current}} = Slim::Buttons::Common::scroll(
	    $client,
	    1,
	    ($#{$ref->{list}} + 1),
	    $ref->{$ref->{current}},
	);
	$client->update();
    },
);

#
#	find_nextmode()
#	---------------
#	Return the name of the next mode when moving from the current
#	list to a sub-list.
#
#	Context keys used:
#
#	    current	The name of the current list
#	    (menuname)  Used as $ref->{$ref->{current}} which is the current
#			position within the current list, numbered from zero
#	    list	The current list data, stored as an arrayref
#
sub find_nextmode
{
    my $ref = $context{(shift)};
    my $nextmode = $ref->{list}->[$ref->{$ref->{current}}];

    return ref($nextmode) ? undef : $nextmode;
}

#
#	main_lines()
#	------------
#	Create and return the two-line display for the main menu.
#
sub main_lines
{
    my $client = shift;
    my $ref = $context{$client};
    my $current = $ref->{$ref->{current}};
    my $list = $ref->{list};

    return (
    	(
	    string('PLUGIN_INFORMATION_MODULE_NAME') .
	    ' (' .
	    ($current + 1) .
	    ' ' .
	    string('OF') .
	    ' ' .
	    ($#$list + 1) .
	    ')'
	),
	string(
	    'PLUGIN_INFORMATION_MENU_' .
	    uc($list->[$current])
	),
	undef,
	Slim::Hardware::VFD::symbol('rightarrow'),
    );
}	

#
#	info_lines()
#	------------
#	Create and return the two-line display for the various information
#	items (except module information).
#
sub info_lines
{
    my $client = shift;
    my $ref = $context{$client};
    my $current = $ref->{$ref->{current}};
    my $item = $ref->{list}->[$current];

    return (
	(
	    string('PLUGIN_INFORMATION_MENU_' . uc($ref->{current})) .
	    ' (' .
	    ($current + 1) .
	    ' ' .
	    string('OF') .
	    ' ' .
	    ($#{$ref->{list}} + 1) .
	    ')'
	),
	(
	    string('PLUGIN_INFORMATION_' . uc($item->[0])) .
	    ': ' .
	    $format{$item->[1]}->($item->[3]->($item->[2] ? $client : undef))
	)
    );
}	

#
#	module_lines()
#	--------------
#	Create and return the two-line display for the module information.
#
sub module_lines
{
    my $client = shift;
    my $ref = $context{$client};
    my $current = $ref->{$ref->{current}};
    my $item = $ref->{list}->[$current];
    my @lines;
    my @info;

    $lines[0] = (
	string('PLUGIN_INFORMATION_MENU_' . uc($ref->{current})) .
	' (' .
	($current + 1) .
	' ' .
	string('OF') .
	' ' .
	($#{$ref->{list}} + 1) .
	') ' .
	"${item}"
    );

    $::VERSION =~ /^(\d+)/;
    push(@info,($1 >= 6) ? string($modules->{$item}) : $modules->{$item});
    push(@info,string('PLUGIN_INFORMATION_DISABLED')) unless $enabled{$item};

    my $version = eval {
	no strict 'refs';
	${"Plugins::${item}::VERSION"};
    };
    if ($@ || !$version) {
	push(@info,string('PLUGIN_INFORMATION_NO_VERSION'));
    }
    else {
    	$version =~ s/^\s+//;
    	$version =~ s/\s+$//;
	push(@info,string('PLUGIN_INFORMATION_VERSION') . ": $version");
    }

    foreach (Slim::Buttons::Plugins::pluginDirs()) {
	my $mtime = (stat(catfile($_,"${item}.pm")))[9];

	if ($mtime) {
	    my $date = string('PLUGIN_INFORMATION_DATE_FORMAT');
	    $date =~ s/\${(\w+?)}/Slim::Utils::Prefs::get($1)/eg;
	    $date =~ s/:%S//;
	    $date = strftime($date,localtime($mtime)),
	    $date =~ s/\|0?(\d+)/$1/g;

	    push(@info,string('PLUGIN_INFORMATION_INSTALLED') . ": $date");
	    last;
	}
    }

    $lines[1] = join(' ' . Slim::Hardware::VFD::symbol('rightarrow') . ' ',@info);
    $lines[2] = $lines[3] = undef;
    @lines;
}	

#
#	player_buffer()
#	---------------
#
sub player_buffer
{
    my $client = shift;
    my $buf = string('PLUGIN_INFORMATION_BUFFER_FORMAT');
    my $size = $format{int}->($client->bufferSize());
    my $fullness = $format{int}->($client->bufferFullness());

    $buf =~ s/\${size}/$size/;
    $buf =~ s/\${fullness}/$fullness/;
    $buf;
}

sub setmode_submenu
{
    my $client = shift;
    my $ref = $context{$client};

    if ($ref->{current} eq 'main') {
	$ref->{current} = $ref->{list}->[$ref->{$ref->{current}}];
    }
    $ref->{list} = $menu{$ref->{current}}->{list};
    $ref->{$ref->{current}} ||= 0;

    $client->lines($menu{$ref->{current}}->{lines});
    $client->update();
}

sub setMode
{
    my $client = shift;

    unless ($modes_set++) {
	foreach (keys %menu) {
	    next if $_ eq 'main';

	    Slim::Buttons::Common::addMode(
		"plugins-information-$_",
		\%functions,
		\&setmode_submenu,
	    );
	}
    }

    unless (ref($modules)) {
	$modules = Slim::Buttons::Plugins::installedPlugins();

	$::VERSION =~ /^(\d+)/;

	if ($1 >= 6) {
	    @module_list = sort { lc(string($modules->{$a})) cmp lc(string($modules->{$b})) } keys %$modules;
	}
	else {
	    @module_list = sort { lc($modules->{$a}) cmp lc($modules->{$b}) } keys %$modules;
	}
	$enabled{$_} = 1 for (Slim::Buttons::Plugins::enabledPlugins($client));
    }

    $context{$client}->{current} = 'main';
    $context{$client}->{list} = \@main_list,
    $context{$client}->{main} ||= 0;

    $client->lines(\&main_lines);
    $client->update();
}

sub getFunctions
{
    \%functions;
}

sub getDisplayName
{
    my $name = 'PLUGIN_INFORMATION_MODULE_NAME';

    $::VERSION =~ /^(\d+)/;
    return ($1 >= 6) ? $name : string($name);
}

sub strings
{
    local $/ = undef;
    <DATA>;
}

1;

__DATA__

PLUGIN_INFORMATION_MODULE_NAME
	EN	SlimServer Information
	FR	Infos SlimServer

PLUGIN_INFORMATION_MENU_PLAYER
	EN	Player Information
	FR	Infos lecteur

PLUGIN_INFORMATION_MENU_SERVER
	EN	Server Information
	FR	Infos serveur

PLUGIN_INFORMATION_MENU_LIBRARY
	EN	Library statistics
	FR	Statistiques

PLUGIN_INFORMATION_MENU_MODULE
	EN	Extra Modules
	FR	Modules plugins

PLUGIN_INFORMATION_NAME
	EN	Name
	FR	Nom lecteur

PLUGIN_INFORMATION_MODEL
	EN	Model
	FR	Modele lecteur

PLUGIN_INFORMATION_FIRMWARE
	EN	Firmware Version
	FR	Version firmware lecteur

PLUGIN_INFORMATION_BUFFER
	EN	Buffer usage

PLUGIN_INFORMATION_UPGRADE
	EN	Firmware Upgrade Available

PLUGIN_INFORMATION_IP_ADDRESS
	EN	IP Address
	FR	Adresse IP

PLUGIN_INFORMATION_PORT_NUMBER
	EN	Port Number
	FR	Port

PLUGIN_INFORMATION_MAC_ADDRESS
	EN	MAC Address
	FR	Adresse MAC

PLUGIN_INFORMATION_SIGNAL
	EN	Wireless Signal Strength

PLUGIN_INFORMATION_VFD_MODEL
	EN	VFD Model

PLUGIN_INFORMATION_VERSION
	EN	Version
	FR	Version

PLUGIN_INFORMATION_CLIENTS
	EN	Total Players Recognised
	FR	Lecteur(s) identifié(s)

PLUGIN_INFORMATION_STREAM_PORT
	EN	Stream Port Number (TCP/UDP)

PLUGIN_INFORMATION_HTTP_PORT
	EN	HTTP Port Number
	FR	Port HTTP

PLUGIN_INFORMATION_ALBUMS
	EN	Total Albums
	FR	Albums

PLUGIN_INFORMATION_ARTISTS
	EN	Total Artists
	FR	Artistes

PLUGIN_INFORMATION_GENRES
	EN	Total Genres
	FR	Genres

PLUGIN_INFORMATION_TRACKS
	EN	Total Tracks
	FR	Morceaux

PLUGIN_INFORMATION_TIME
	EN	Total Playing Time
	FR	Durée totale

PLUGIN_INFORMATION_INSTALLED
	EN	Installed
	FR	Installé

PLUGIN_INFORMATION_DISABLED
	EN	DISABLED
	FR	DESACTIVE

PLUGIN_INFORMATION_NO_VERSION
	EN	No version number
	FR	Pas de version

PLUGIN_INFORMATION_DATE_FORMAT
	EN	${shortdateFormat} at ${timeFormat}
	FR	${shortdateFormat} à ${timeFormat}

PLUGIN_INFORMATION_BUFFER_FORMAT
	EN	${fullness} of ${size} bytes

PLUGIN_INFORMATION_YES
	EN	Yes
	FR	Oui

PLUGIN_INFORMATION_NO
	EN	No
	FR	Non

PLUGIN_INFORMATION_OF
	EN	of

PLUGIN_INFORMATION_NA
	EN	N/A


