package Plugins::RssNews;

# RSS News Browser
# Copyright (c) 2006 Logitech
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License, 
# version 2.
#
# This is a reimplementation of the old RssNews plugin based on
# the Podcast Browser plugin.
#
# $Id: RssNews.pm 11880 2007-05-01 23:27:36Z mherger $

use strict;

use constant FEEDS_VERSION => 1.0;

use HTML::Entities;
use XML::Simple;

use Slim::Buttons::XMLBrowser;
use Slim::Formats::XML;
use Slim::Utils::Cache;
use Slim::Utils::Misc;
use Slim::Utils::Strings qw(string);

# Default feed list
my @default_feeds = (
	{
		name  => 'BBC News World Edition',
		value => 'http://news.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml',
	},
	{
		name  => 'CNET News.com',
		value => 'http://news.com.com/2547-1_3-0-5.xml',
	},
	{
		name  => 'New York Times Home Page',
		value => 'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml',
	},
	{
		name  => 'RollingStone.com Music News',
		value => 'http://www.rollingstone.com/rssxml/music_news.xml',
	},
	{
		name  => 'Slashdot',
		value => 'http://rss.slashdot.org/Slashdot/slashdot',
	},
	{
		name  => 'Yahoo! News: Business',
		value => 'http://rss.news.yahoo.com/rss/business',
	},
);

my @feeds = ();
my %feed_names; # cache of feed names

# in screensaver mode, number of items to display per channel before switching
my $screensaver_items_per_feed;

# $refresh_sec is the minimum time in seconds between refreshes of the ticker from the RSS.
# Please do not lower this value. It prevents excessive queries to the RSS.
my $refresh_sec = 60 * 60;

# per-client screensaver state information
my $savers = {};

sub enabled {
	return ($::VERSION ge '6.3');
}

sub initPlugin {
	$::d_plugins && msg("RSS Plugin initializing.\n");

	Slim::Buttons::Common::addMode('PLUGIN.RSS', getFunctions(), \&setMode);

	my @feedURLPrefs  = Slim::Utils::Prefs::getArray("plugin_RssNews_feeds");
	my @feedNamePrefs = Slim::Utils::Prefs::getArray("plugin_RssNews_names");
	my $feedsModified = Slim::Utils::Prefs::get("plugin_RssNews_feeds_modified");
	my $version       = Slim::Utils::Prefs::get("plugin_RssNews_feeds_version");
	
	$screensaver_items_per_feed = Slim::Utils::Prefs::get('plugin_RssNews_items_per_feed');
	if (!defined $screensaver_items_per_feed) {

		$screensaver_items_per_feed = 3;
		Slim::Utils::Prefs::set('plugin_RssNews_items_per_feed', $screensaver_items_per_feed);
	}

	@feeds = ();

#        |requires Client
#        |  |is a Query
#        |  |  |has Tags
#        |  |  |  |Function to call
#        C  Q  T  F
    Slim::Control::Request::addDispatch(['rss', 'items', '_index', '_quantity'],
        [0, 1, 1, \&cliQuery]);


	# No prefs set or we've had a version change and they weren't modified, 
	# so we'll use the defaults
	if (scalar(@feedURLPrefs) == 0 ||
		(!$feedsModified && (!$version  || $version != FEEDS_VERSION))) {
		# use defaults
		# set the prefs so the web interface will work.
		revertToDefaults();
	} else {
		# use prefs
		my $i = 0;
		while ($i < scalar(@feedNamePrefs)) {

			push @feeds, {
				name  => $feedNamePrefs[$i],
				value => $feedURLPrefs[$i],
				type  => 'link',
			};
			$i++;
		}
	}

	if ($::d_plugins) {
		msg("RSS Feed Info:\n");

		foreach (@feeds) {
			msg($_->{'name'} . ", " . $_->{'value'} . "\n");
		}

		msg("\n");
	}

	# feed_names should reflect current names
	%feed_names = ();

	map { $feed_names{$_->{'value'} } = $_->{'name'}} @feeds;
	
	updateOPMLCache( \@feeds );
}

sub revertToDefaults {
	@feeds = @default_feeds;

	my @urls  = map { $_->{'value'} } @feeds;
	my @names = map { $_->{'name'}  } @feeds;

	Slim::Utils::Prefs::set('plugin_RssNews_feeds', \@urls);
	Slim::Utils::Prefs::set('plugin_RssNews_names', \@names);
	Slim::Utils::Prefs::set('plugin_RssNews_feeds_version', FEEDS_VERSION);

	# feed_names should reflect current names
	%feed_names = ();

	map { $feed_names{$_->{'value'}} = $_->{'name'} } @feeds;
	
	updateOPMLCache( \@feeds );
}

sub getDisplayName {
	return 'PLUGIN_RSSNEWS';
}

sub getFunctions {
	return {};
}

sub setMode {
	my $client = shift;
	my $method = shift;

	if ($method eq 'pop') {
		Slim::Buttons::Common::popMode($client);
		return;
	}

	# use INPUT.Choice to display the list of feeds
	my %params = (
		header => '{PLUGIN_RSSNEWS} {count}',
		listRef => \@feeds,
		modeName => 'RSS Plugin',
		onRight => sub {
			my $client = shift;
			my $item = shift;
			my %params = (
				url     => $item->{'value'},
				title   => $item->{'name'},
				expires => $refresh_sec,
			);
			Slim::Buttons::Common::pushMode($client, 'xmlbrowser', \%params);
		},

		overlayRef => [
			undef,
			Slim::Display::Display::symbol('rightarrow') 
		],
	);

	Slim::Buttons::Common::pushMode($client, 'INPUT.Choice', \%params);
}

sub cliQuery {
	my $request = shift;
	
	$::d_plugins && msg("RSS: cliQuery()\n");
	
	# Get OPML list of feeds from cache
	my $cache = Slim::Utils::Cache->new();
	my $opml = $cache->get( 'rss_opml' );
	Slim::Buttons::XMLBrowser::cliQuery('rss', $opml, $request, $refresh_sec);
}


# Update the hashref of RSS feeds for use with the web UI
sub updateOPMLCache {
	my $feeds = shift;
	
	my $outline = [];
	for my $item ( @{$feeds} ) {
		push @{$outline}, {
			'name'  => $item->{'name'},
			'url'   => $item->{'value'},
			'value' => $item->{'value'},
			'type'  => $item->{'type'},
			'items' => [],
		};
	}
	
	my $opml = {
		'title' => string('PLUGIN_RSSNEWS'),
		'url'   => 'rss_opml',			# Used so XMLBrowser can look this up in cache
		'type'  => 'opml',
		'items' => $outline,
	};
		
	my $cache = Slim::Utils::Cache->new();
	$cache->set( 'rss_opml', $opml, '10days' );
}

# for configuring via web interface
sub setupGroup {
	my %Group = (
		PrefOrder => [
			'plugin_RssNews_items_per_feed',
			'plugin_RssNews_reset',
			'plugin_RssNews_feeds',
		],
		GroupHead => 'PLUGIN_RSSNEWS',
		GroupDesc => 'SETUP_GROUP_PLUGIN_RSSNEWS_DESC',
		GroupLine => 1,
		GroupSub  => 1,
		Suppress_PrefSub  => 1,
		Suppress_PrefLine => 1,
	);

	my %Prefs = (
		
		plugin_RssNews_items_per_feed => {
			'validate'       => \&Slim::Utils::Validate::isInt,
			'validateArgs'  => [1,undef,1],
			'onChange'      => sub {
				$screensaver_items_per_feed = $_[1]->{plugin_RssNews_items_per_feed}->{new};
				Slim::Utils::Prefs::set('plugin_RssNews_items_per_feed', $screensaver_items_per_feed);
			},
		},
		
		plugin_RssNews_reset => {
			'onChange'      => sub {
				Slim::Utils::Prefs::set("plugin_RssNews_feeds_modified", undef);
				Slim::Utils::Prefs::set("plugin_RssNews_feeds_version", undef);
				revertToDefaults();
			},
			'inputTemplate' => 'setup_input_submit.html',
			'changeIntro'   => 'PLUGIN_RSSNEWS_RESETTING',
			'ChangeButton'  => 'SETUP_PLUGIN_RSSNEWS_RESET_BUTTON',
			'dontSet'       => 1,
			'changeMsg'     => '',
		},

		plugin_RssNews_feeds => { 
			'isArray'          => 1,
			'arrayAddExtra'    => 1,
			'arrayDeleteNull'  => 1,
			'arrayDeleteValue' => '',
			'arrayBasicValue'  => 0,
			'PrefSize'         => 'large',
			'inputTemplate'    => 'setup_input_array_txt.html',
			'PrefInTable'      => 1,
			'showTextExtValue' => 1,
			'externalValue'    => sub {
				my ($client, $value, $key) = @_;

				if ($key =~ /^(\D*)(\d+)$/ && ($2 < scalar(@feeds))) {
					return $feeds[$2]->{'name'};
				}

				return '';
			},
			'onChange'         => \&updateFeedNames,
			'changeMsg'        => 'SETUP_PLUGIN_RSSNEWS_FEEDS_CHANGE',
		},
	);

	return (\%Group, \%Prefs);
}

sub updateFeedNames {
	my @feedURLPrefs = Slim::Utils::Prefs::getArray("plugin_RssNews_feeds");
	my @feedNamePrefs;

	# verbose debug
	if ($::d_plugins) {

		msg("RSS: updateFeedNames urls:\n");
		msg(Data::Dump::dump(\@feedURLPrefs));
	}

	# case 1: we're reverting to default
	if (scalar(@feedURLPrefs) == 0) {
		revertToDefaults();
	} else {
		# case 2: url list edited

		my $i = 0;
		while ($i < scalar(@feedURLPrefs)) {

			my $url = $feedURLPrefs[$i];
			my $name = $feed_names{$url};

			if ($name && $name !~ /^http\:/) {

				# no change
				$feedNamePrefs[$i] = $name;

			} elsif ($url =~ /^http\:/) {

				# does a synchronous get
				# XXX: This should use async instead, but not a very high priority 
				# as this code is not used very much
				my $xml = Slim::Formats::XML->getFeedSync($url);

				if ($xml && exists $xml->{'channel'}->{'title'}) {

					# here for podcasts and RSS
					$feedNamePrefs[$i] = Slim::Formats::XML::unescapeAndTrim($xml->{'channel'}->{'title'});

				} elsif ($xml && exists $xml->{'head'}->{'title'}) {

					# here for OPML
					$feedNamePrefs[$i] = Slim::Formats::XML::unescapeAndTrim($xml->{'head'}->{'title'});

				} else {
					# use url as title since we have nothing else
					$feedNamePrefs[$i] = $url;
				}

			} else {
				# use url as title since we have nothing else
				$feedNamePrefs[$i] = $url;
			}

			$i++;
		}

		# if names array contains more than urls, delete the extras
		while ($feedNamePrefs[$i]) {
			delete $feedNamePrefs[$i];
			$i++;
		}

		# save updated names to prefs
		Slim::Utils::Prefs::set('plugin_RssNews_names', \@feedNamePrefs);

		# runtime list must reflect changes
		@feeds = ();
		$i = 0;

		while ($i < scalar(@feedNamePrefs)) {

			push @feeds, {
				name => $feedNamePrefs[$i],
				value => $feedURLPrefs[$i]
			};

			$i++;
		}

		# feed_names should reflect current names
		%feed_names = ();

		map { $feed_names{$_->{'value'}} = $_->{'name'} } @feeds;
		
		updateOPMLCache( \@feeds );
	}

}

################################
# ScreenSaver Mode

sub screenSaver {
	Slim::Utils::Strings::addStrings(strings());

	Slim::Buttons::Common::addSaver(
		'SCREENSAVER.rssnews',
		getScreensaverRssNews(),
		\&setScreensaverRssNewsMode,
		\&leaveScreenSaverRssNews,
		'PLUGIN_RSSNEWS_SCREENSAVER'
	);
}

sub getScreensaverRssNews {

	return {
		'done' => sub  {
			my ($client, $funct, $functarg) = @_;

			Slim::Buttons::Common::popMode($client);
			$client->update;

			# pass along ir code to new mode if requested
			if (defined $functarg && $functarg eq 'passback') {
				Slim::Hardware::IR::resendButton($client);
			}
		}
	};
}

sub setScreensaverRssNewsMode {
	my $client = shift;

	# init params
	$savers->{$client} = {
		newfeed  => 1,
		line1    => 0,
	};

	$client->lines(\&blankLines);

	# start tickerUpdate in future after updates() caused by server mode change
	Slim::Utils::Timers::setTimer(
		$client, 
		Time::HiRes::time() + 0.5,
		\&tickerUpdate
	);
}

# kill tickerUpdate
sub leaveScreenSaverRssNews {
	my $client = shift;

	Slim::Utils::Timers::killTimers($client, \&tickerUpdate);
	Slim::Utils::Timers::killTimers($client, \&tickerUpdateCheck);

	delete $savers->{$client};
	
	$::d_plugins && msg("RSS: Left screensaver mode\n");
}

sub tickerUpdate {
	my $client = shift;

	if ( $savers->{$client}->{newfeed} ) {
		# we need to fetch the next feed
		getNextFeed( $client );
	}
	else {
		tickerUpdateContinue( $client );
	}
}

sub getNextFeed {
	my $client = shift;
	
	# select the next feed and fetch it
	my $index = $savers->{$client}->{feed_index} || 0;
	$index++;
	
	if ( $index > scalar @feeds ) {
		$index = 1;
		# reset error count after looping around to the beginning
		$savers->{$client}->{feed_error} = 0;
	}
	
	$savers->{$client}->{feed_index} = $index;
	
	my $url = $feeds[$index - 1]->{'value'};
	
	$::d_plugins && msg("RSS: Fetching next feed: $url\n");
	
	if ( !$savers->{$client}->{current_feed} ) {
		$client->update( {
			'line' => [ 
				$client->string('PLUGIN_RSSNEWS'),
				$client->string('PLUGIN_RSSNEWS_WAIT')
			],
		} );
	}
	
	Slim::Formats::XML->getFeedAsync( 
		\&gotNextFeed,
		\&gotError,
		{
			'url'     => $url,
			'client'  => $client,
			'expires' => $refresh_sec,
		},
	);
}

sub gotNextFeed {
	my ( $feed, $params ) = @_;
	my $client = $params->{'client'};
	
	# Bug 3860, If the user left screensaver mode while we were fetching the feed, cancel out
	if ( !exists $savers->{$client} ) {
		return;
	}
	
	$savers->{$client}->{current_feed} = $feed;
	
	tickerUpdateContinue( $client );
}

sub gotError {
	my ( $error, $params ) = @_;
	my $client = $params->{'client'};
	
	# Bug 3860, If the user left screensaver mode while we were fetching the feed, cancel out
	if ( !exists $savers->{$client} ) {
		return;
	}
	
	# Bug 1664, skip broken feeds in screensaver mode
	
	$::d_plugins && msg("RSS: Error loading feed: $error, skipping\n");
	
	my $errors = $savers->{$client}->{feed_error} || 0;
	$errors++;
	$savers->{$client}->{feed_error} = $errors;
	
	if ( $errors == scalar @feeds ) {
		$::d_plugins && msg("RSS: All feeds failed, giving up\n");
		
		$client->update( {
			'line' => [ $client->string('PLUGIN_RSSNEWS'),
						$client->string('PLUGIN_RSSNEWS_ERROR') ],
		} );
	}
	else {	
		getNextFeed( $client );
	}
}

sub tickerUpdateContinue {
	my $client = shift;
	
	# Bug 3860, If the user left screensaver mode, cancel out
	if ( !exists $savers->{$client} ) {
		return;
	}
	
	$savers->{$client}->{line1} = 0;

	# add item to ticker
	$client->update( tickerLines($client) );

	my ($complete, $queue) = $client->scrollTickerTimeLeft();
	my $newfeed = $savers->{$client}->{newfeed};

	# schedule for next item as soon as queue drains if same feed or after ticker completes if new feed
	my $next = $newfeed ? $complete : $queue;

	Slim::Utils::Timers::setTimer(
		$client, 
		Time::HiRes::time() + ( ($next > 1) ? $next : 1),
		\&tickerUpdate
	);
}

# check to see if ticker is empty and schedule immediate ticker update if so
sub tickerUpdateCheck {
	my $client = shift;

	my ($complete, $queue) = $client->scrollTickerTimeLeft();

	if ( $queue == 0 && Slim::Utils::Timers::killTimers($client, \&tickerUpdate) ) {
		tickerUpdate($client);
	}
}

# lines when called by server - e.g. on screensaver start or change of font size
# add undef line2 item to ticker, schedule tickerUpdate to add to ticker if necessary
sub blankLines {
	my $client = shift;

	my $parts = {
		'line'   => [ $savers->{$client}->{line1} || '' ],
		'ticker' => [],
	};

	# check after the update calling this function is complete to see if ticker is empty
	# (to refill ticker on font size change as this clears current ticker)
	Slim::Utils::Timers::killTimers( $client, \&tickerUpdateCheck );	
	Slim::Utils::Timers::setTimer(
		$client, 
		Time::HiRes::time() + 0.1,
		\&tickerUpdateCheck
	);

	return $parts;
}

# lines for tickerUpdate to add to ticker
sub tickerLines {
	my $client = shift;

	my $parts         = {};
	my $new_feed_next = 0; # use new feed next call

	# the current RSS feed
	my $feed = $savers->{$client}->{current_feed};

	assert( ref $feed eq 'HASH', "current rss feed not set\n");

	# the current item within each feed.
	my $current_items = $savers->{$client}->{current_items};

	if ( !defined $current_items ) {

		$current_items = {
			$feed => {
				'next_item'  => 0,
				'first_item' => 0,
			},
		};

	}
	elsif ( !defined $current_items->{$feed} ) {

		$current_items->{$feed} = {
			'next_item'  => 0,
			'first_item' => 0
		};
	}
	
	# add item to ticker or display error and wait for tickerUpdate to retrieve news
	if ( defined $feed ) {
	
		my $line1 = Slim::Formats::XML::unescapeAndTrim( $feed->{'title'} );
		my $i     = $current_items->{$feed}->{'next_item'};
		
		my $title       = $feed->{'items'}->[$i]->{'title'};
		my $description = $feed->{'items'}->[$i]->{'description'} || '';

		# How to display items shown by screen saver.
		# %1\$s is item 'number'	XXX: number not used?
		# %2\$s is item title
		# %3\%s is item description
		my $screensaver_item_format = "%2\$s -- %3\$s";
		
		# we need to limit the number of characters we add to the ticker, 
		# because the server could crash rendering on pre-SqueezeboxG displays.
		my $screensaver_chars_per_item = 1024;
		
		my $line2 = sprintf(
			$screensaver_item_format,
			$i + 1,
			Slim::Formats::XML::unescapeAndTrim($title),
			Slim::Formats::XML::unescapeAndTrim($description)
		);

		if ( length $line2 > $screensaver_chars_per_item ) {

			$line2 = substr $line2, 0, $screensaver_chars_per_item;

			$::d_plugins && msg("RSS: screensaver character limit exceeded - truncating.\n");
		}

		$current_items->{$feed}->{'next_item'} = $i + 1;

		if ( !exists( $feed->{'items'}->[ $current_items->{$feed}->{'next_item'} ] ) ) {

			$current_items->{$feed}->{'next_item'}  = 0;
			$current_items->{$feed}->{'first_item'} -= ($i + 1);

			if ( $screensaver_items_per_feed >= ($i + 1) ) {

				$new_feed_next = 1;

				$current_items->{$feed}->{'first_item'} = 0;
			}
		}

		if ( ($current_items->{$feed}->{'next_item'} - 
		      $current_items->{$feed}->{'first_item'}) >= $screensaver_items_per_feed ) {

			# displayed $screensaver_items_per_feed of this feed, move on to next saving position
			$new_feed_next = 1;
			$current_items->{$feed}->{'first_item'} = $current_items->{$feed}->{'next_item'};
		}

		$parts = {
			'line'   => [ $line1 ],
			'ticker' => [ undef, $line2 ],
		};

		$savers->{$client}->{line1} = $line1;
		$savers->{$client}->{current_items} = $current_items;
	}
	else {

		$parts = {
			'line' => [ "RSS News - ". $feed->{'title'}, $client->string('PLUGIN_RSSNEWS_WAIT') ]
		};

		$new_feed_next = 1;
	}

	$savers->{$client}->{newfeed} = $new_feed_next;

	return $parts;
}

sub strings {

	return q!
PLUGIN_RSSNEWS
	DE	RSS-Nachrichtenticker
	EN	RSS News Ticker
	ES	Teletipo de noticias RSS
	FR	Aggrégateur RSS
	HE	טיקר RSS של חדשות
	IT	RSS News Ticker
	NL	RSS-nieuwsberichten

PLUGIN_RSSNEWS_ADD_NEW
	DE	Neuen Feed hinzufügen -->
	EN	Add new feed -->
	ES	Agregar fuente nueva -->
	FR	Ajouter flux -->
	HE	הוסף הזנה חדשה -->
	IT	Aggiungi un nuovo feed -->
	NL	Nieuw kanaal toevoegen -->

PLUGIN_RSSNEWS_WAIT
	DE	Feed wird angefordert. Bitte warten ...
	EN	Please wait, requesting feed...
	ES	Espere, solicitando fuente...
	FR	Veuillez patienter, connexion au flux...
	HE	אנא המתן, מבקש הזנה...
	IT	Attendere. Richiesta feed in corso...
	NL	Kanaal wordt opgevraagd. Een ogenblik geduld.

PLUGIN_RSSNEWS_ERROR
	DE	Fehler beim Laden des RSS-Feed
	EN	Failed to retrieve RSS feed
	ES	Fallo al obtener fuente RSS
	FR	Impossible de charger le flux
	HE	כשל באחזור הזנת RSS
	IT	Impossibile recuperare feed RSS
	NL	Fout bij ophalen RSS-kanaal

PLUGIN_RSSNEWS_NO_DESCRIPTION
	DE	Keine Beschreibung verfügbar
	EN	Description not available
	ES	Descripción no disponible
	FR	Description non disponible
	HE	אין תיאור זמין
	IT	Descrizione non disponibile
	NL	Beschrijving niet beschikbaar

PLUGIN_RSSNEWS_NO_TITLE
	CS	Název není dostupný
	DE	Kein Titel verfübar
	EN	Title not available
	ES	Título no disponible
	FR	Titre non disponible
	HE	אין כותרת זמינה
	IT	Titolo non disponibile
	NL	Titel niet beschikbaar

PLUGIN_RSSNEWS_SCREENSAVER
	DE	RSS-Nachrichtenticker
	EN	RSS News Ticker
	ES	Teletipo de noticias RSS
	FR	Aggrégateur RSS
	HE	טיקר RSS של חדשות
	IT	RSS News Ticker
	NL	RSS-nieuwsberichten

PLUGIN_RSSNEWS_NAME
	DE	RSS-Nachrichtenticker
	EN	RSS News Ticker
	ES	Teletipo de noticias RSS
	FR	Aggrégateur RSS
	HE	טיקר RSS של חדשות
	IT	RSS News Ticker
	NL	RSS-nieuwsberichten

PLUGIN_RSSNEWS_SCREENSAVER_SETTINGS
	DE	Einstellungen für RSS-Nachrichten-Bildschirmschoner
	EN	RSS News Screensaver Settings
	ES	Configuración de protector de pantalla de noticias RSS
	FR	Paramètres Ecran de veille Aggrégateur RSS
	HE	הגדרות שומר המסך של RSS של חדשות
	IT	Impostazioni screen saver RSS News
	NL	Instellingen van RSS-nieuwsschermbeveiliger

PLUGIN_RSSNEWS_SCREENSAVER_ACTIVATE
	DE	Aktuellen Bildschirmschoner wählen
	EN	Select Current Screensaver
	ES	Seleccionar protector de pantalla actual
	FR	Sélectionner l'écran de veille en cours
	HE	בחר את שומר המסך הנוכחי
	IT	Seleziona lo screen saver corrente
	NL	Huidige schermbeveiliger selecteren

PLUGIN_RSSNEWS_SCREENSAVER_ACTIVATE_TITLE
	CS	Aktuální spořič
	DE	Aktueller Bildschirmschoner
	EN	Current Screensaver
	ES	Protector de pantalla actual
	FR	Ecran de veille en cours
	HE	שומר המסך הנוכחי
	IT	Screen saver corrente
	NL	Huidige schermbeveiliger

PLUGIN_RSSNEWS_SCREENSAVER_ACTIVATED
	CS	Použít RSS News jako aktuální spořič
	DE	RSS-Nachrichten als Bildschirmschoner verwenden
	EN	Use RSS News as current screensaver
	ES	Usar noticias RSS como protector de pantalla actual
	FR	Utiliser l'aggrégateur RSS comme écran de veille
	HE	השתמש ב-RSS של חדשות כשומר המסך הנוכחי
	IT	Usa RSS News come screen saver corrente
	NL	RSS-nieuws als huidige schermbeveiliger gebruiken

PLUGIN_RSSNEWS_SCREENSAVER_DEFAULT
	DE	Standard-Bildschirmschoner verwenden (nicht RSS-Nachrichten)
	EN	Use default screensaver (not RSS News)
	ES	Usar protector de pantalla predeterminado (no noticias RSS)
	FR	Utiliser l'écran de veille par défaut (hors aggrégateur RSS)
	HE	השתמש בשומר המסך הנוכחי (לא RSS של חדשות)
	IT	Usa lo screen saver predefinito (non RSS News)
	NL	Standaardschermbeveiliger gebruiken (niet RSS-nieuws)

PLUGIN_RSSNEWS_SCREENSAVER_ENABLE
	DE	Nachrichtenticker wird als Bildschirmschoner aktiviert ...
	EN	Activating ticker as current screensaver
	ES	Activando teletipo como nuevo protector de pantalla
	FR	Activation de l'aggrégateur RSS comme écran de veille
	HE	מפעיל את הטיקר כשומר המסך הנוכחי
	IT	Attivazione del ticker come screen saver corrente
	NL	RSS-nieuwsberichten worden als schermbeveiliger ingeschakeld

PLUGIN_RSSNEWS_SCREENSAVER_DISABLE
	DE	Standard-Bildschirmschoner wird aktiviert ...
	EN	Returning to default screensaver
	ES	Volviendo al protector de pantalla predeterminado
	FR	Rétablissement de l'écran de veille par défaut
	HE	חזרה לשומר המסך המוגדר כברירת מחדל
	IT	Ritorno allo screen saver predefinito
	NL	Terug naar standaardschermbeveiliger

PLUGIN_RSSNEWS_ERROR_IN_FEED
	DE	Fehler beim Parsen des RSS Feed
	EN	Error parsing RSS feed
	ES	Error al analizar fuente RSS
	FR	Erreur de lecture du flux
	HE	שגיאה בניתוח הזנת RSS
	IT	Errore durante l'analisi del feed RSS
	NL	Fout bij parseren RSS-kanaal

PLUGIN_RSSNEWS_LOADING_FEED
	DE	RSS-Feed wird geladen...
	EN	Loading RSS feed...
	ES	Cargando fuente RSS
	FR	Chargement du flux...
	HE	טוען הזנת RSS...
	IT	Caricamento del feed RSS...
	NL	RSS-kanaal wordt geladen...

SETUP_GROUP_PLUGIN_RSSNEWS_DESC
	DE	Mit dem Plugin 'RSS-Nachrichtenticker' können Artikel aus RSS-Feeds angezeigt werden. Mit den folgenden Einstellungen können Sie festlegen, welche RSS-Feeds wie angezeigt werden sollen. Klicken Sie auf 'Ändern', wenn Sie fertig sind.
	EN	The RSS News Ticker plugin can be used to browse and display items from RSS Feeds. The preferences below can be used to determine which RSS Feeds to use and control how they are displayed. Click on the Change button when you are done.
	ES	El complemento de teletipo de noticias RSS se puede usar para examinar y mostrar elementos de fuentes RSS. Las preferencias siguientes se pueden usar para determinar qué fuentes RSS se deben usar y para controlar cómo deben mostrarse. Haga clic en el botón Cambiar cuando haya finalizado.
	FR	Le plugin Aggrégateur RSS vous permet de parcourir et d'afficher le contenu de flux RSS. Les paramètres ci-dessous permettent de sélectionner les flux RSS et de modifier leur affichage sur la platine. Cliquez sur Modifier une fois les modifications effectuées.
	HE	ניתן להשתמש ביישום ה-Plugin 'טיקר RSS של חדשות' לעיון בפריטים מהזנות RSS ולהצגתם. ניתן להשתמש בהעדפות שלהלן כדי לקבוע באילו הזנות RSS להשתמש וכדי לשלוט באופן ההצגה שלהן. לסיום, לחץ על הלחצן 'שנה'.
	IT	È possibile utilizzare il plugin RSS News Ticker per sfogliare e visualizzare argomenti dei feed RSS. Per specificare i feed RSS da utilizzare e impostarne il tipo di visualizzazione, utilizzare le preferenze indicate di seguito. Al termine delle operazioni, fare clic sul pulsante Cambia.
	NL	Met de plug-in voor RSS-nieuwsberichten kun je items van RSS-kanalen bekijken en weergeven. Met de instellingen hieronder kun je bepalen welke RSS-kanalen je wilt gebruiken en hoe ze worden weergegeven. Klik op de knop 'Veranderen' wanneer je klaar bent.

SETUP_PLUGIN_RSSNEWS_FEEDS
	DE	RSS-Feeds ändern
	EN	Modify RSS feeds
	ES	Modificar fuentes RSS
	FR	Modifier les flux RSS
	HE	שינוי הזנות RSS
	IT	Modifica i feed RSS
	NL	RSS-kanalen wijzigen

SETUP_PLUGIN_RSSNEWS_FEEDS_DESC
	DE	Dies ist die Liste der anzuzeigenden RSS-Feeds. Geben Sie zum Hinzufügen eines neuen einfach die URL in die leere Zeile ein. Löschen Sie zum Entfernen eines Feeds die URL aus der entsprechenden Zeile. Sie können die URL eines vorhandenen Feed ändern, indem Sie den Textwert bearbeiten. Klicken Sie auf 'Ändern', wenn Sie fertig sind.
	EN	This is the list of RSS Feeds to display. To add a new one, just type its URL into the empty line. To remove one, simply delete the URL from the corresponding line. To change the URL of an existing feed, edit its text value. Click on the Change button when you are done.
	ES	Ésta es la lista de fuentes RSS que se debe mostrar. Para agregar una nueva, escriba su URL en la línea vacía. Para quitar una, elimine la URL de la línea correspondiente. Para cambiar la URL de una fuente existente, edite su valor de texto. Haga clic en el botón Cambiar cuando haya finalizado.
	FR	Il s'agit de la liste des flux RSS à afficher. Pour ajouter un flux, spécifiez son URL sur une ligne vide. Pour en supprimer un, supprimez l'URL de la liste correspondante. Pour modifier l'URL d'un flux existant, modifiez la ligne correspondante. Cliquez sur Modifier une fois les modifications effectuées.
	HE	זוהי הרשימה של הזנות RSS שיש להציג. להוספת הזנה חדשה, פשוט הקלד את כתובת ה-URL שלה בשורה הריקה. להסרת הזנה, פשוט מחק את כתובת ה-URL שלה מהשורה המתאימה. לשינוי כתובת ה-URL של הזנה קיימת, ערוך את ערך הטקסט שלה. לסיום, לחץ על הלחצן 'שנה'.
	IT	Elenco dei feed RSS da visualizzare. Per aggiungere un nuovo feed, digitare il relativo URL in una riga vuota. Per rimuoverne uno, eliminare semplicemente l'URL dalla riga corrispondente. Per cambiare l'URL di un feed esistente, modificare il contenuto del testo. Al termine dell'operazione, fare clic sul pulsante Cambia.
	NL	Dit is de lijst van RSS-kanalen die weergegeven moeten worden. Als je een nieuw kanaal wilt toevoegen, typ je gewoon de URL ervan in de lege regel. Verwijder de URL uit de overeenkomstige regel om een kanaal weg te halen. Wil je de URL van een bestaand kanaal wijzigen, dan verander je de tekstwaarde. Klik op de knop 'Veranderen' wanneer je klaar bent.

SETUP_PLUGIN_RSSNEWS_RESET
	DE	Standard-Feeds wiederherstellen
	EN	Reset default RSS feeds
	ES	Restablecer fuentes RSS predeterminadas
	FR	Réinitialiser les flux RSS par défaut
	HE	איפוס הזנות ה-RSS המוגדרות כברירת מחדל
	IT	Reimposta i feed RSS predefiniti
	NL	Standaard RSS-kanalen opnieuw instellen

SETUP_PLUGIN_RSSNEWS_RESET_DESC
	DE	Klicken Sie auf 'Zurücksetzen', um die Standard-RSS-Feeds wiederherzustellen.
	EN	Click the Reset button to revert to the default set of RSS Feeds.
	ES	Haga clic en el botón Restablecer para volver al conjunto de fuentes RSS predeterminado.
	FR	Cliquez sur Réinitialiser pour rétablir la liste par défaut des flux RSS.
	HE	לחץ על הלחצן 'איפוס' כדי לחזור אל ערכת ברירת המחדל של הזנות RSS.
	IT	Premere il pulsante Reimposta per ritornare al set di feed RSS predefinito.
	NL	Klik op de knop Opnieuw instellen om de standaardset RSS-kanalen te herstellen.

PLUGIN_RSSNEWS_RESETTING
	DE	Standard-RSS-Feeds werden wiederhergestellt ...
	EN	Resetting to default RSS Feeds.
	ES	Restableciendo las fuentes RSS predeterminadas
	FR	Réinitialisation des flux par défaut.
	HE	איפוס להזנות RSS המוגדרות כברירת מחדל.
	IT	Reimpostazione sui feed RSS predefiniti.
	NL	Standaard RSS-kanalen worden hersteld.

SETUP_PLUGIN_RSSNEWS_RESET_BUTTON
	CS	Resetovat
	DE	Zurücksetzen
	EN	Reset
	ES	Restablecer
	FR	Réinitialiser
	HE	איפוס
	IT	Reimposta
	NL	Opnieuw instellen

SETUP_PLUGIN_RSSNEWS_ITEMS_PER_FEED
	DE	Anzahl Einträge pro Feed
	EN	Items displayed per channel
	ES	Elementos mostrados por canal
	FR	Nombre d'éléments par canal
	HE	פריטים מוצגים לפי ערוץ
	IT	Argomenti visualizzati per canale
	NL	Weergegeven items per kanaal

SETUP_PLUGIN_RSSNEWS_ITEMS_PER_FEED_DESC
	DE	Die Anzahl Einträge, die im Bildschirmschonermodus pro Feed angezeigt werden sollen. Eine größere Anzahl bedeutet, dass mehr Einträge angezeigt werden, bevor der nächste Feed angezeigt wird.
	EN	The maximum number of items displayed for each feed while the screensaver is active. A larger value implies that the screensaver will display more items before switching to the next feed.
	ES	El número máximo de elementos mostrados para cada fuente mientras el protector de pantalla está activo. Un valor más alto implica que el protector de pantalla mostrará más elementos antes de pasar a la fuente siguiente.
	FR	Nombre maximal d'éléments affichés pour chaque flux lorsque l'écran de veille est actif. Un nombre élevé signifie que l'écran de veille affiche plus d'éléments avant de passer au flux suivant.
	HE	המספר המרבי של פריטים המוצגים עבור כל הזנה בשעה ששומר המסך פעיל. ערך גבוה מסמל שיוצגו בשומר המסך יותר פריטים לפני מעבר להזנה הבאה.
	IT	Numero massimo di argomenti visualizzati per ogni feed quando lo screen saver è attivo. Se si imposta un valore maggiore sullo screen saver viene visualizzato un numero di argomenti maggiore prima di passare al feed successivo.
	NL	Het maximumaantal items dat per kanaal wordt weergegeven terwijl de schermbeveiliger actief is. Een hogere waarde betekent dat de schermbeveiliger meer items laat zien, voordat deze naar het volgende kanaal springt.

SETUP_PLUGIN_RSSNEWS_ITEMS_PER_FEED_CHOOSE
	CS	Položek na kanál
	DE	Einträge pro Feed
	EN	Items per channel
	ES	Elementos por canal
	FR	Eléments par canal
	HE	פריטים לפי ערוץ
	IT	Argomenti per canale
	NL	Items per kanaal

SETUP_PLUGIN_RSSNEWS_FEEDS_CHANGE
	DE	RSS-Feed-Liste wurde geändert.
	EN	RSS Feeds list changed.
	ES	Se ha cambiado la lista de fuentes RSS.
	FR	Liste des flux RSS modifiée.
	HE	הרשימה של הזנות RSS השתנתה.
	IT	Elenco dei feed RSS modificato.
	NL	RSS-kanalenlijst gewijzigd.
!

}

1;
