[Slim-Checkins] r11744 - in /trunk/server: ./ Slim/Control/ Slim/Plugin/CLI/ Slim/Plugin/DateTime/ Slim/Plugin/DateTime/HTML/EN/plugins/DateTime/settings/ Slim/Plugin/Favorites/ Slim/Plugin/Favorites/HTML/EN/plugins/Favorites/settings/ Slim/Plugin/Podcast/ Slim/Plugin/Podcast/HTML/EN/plugins/Podcast/settings/ Slim/Plugin/RadioTime/ Slim/Plugin/RadioTime/HTML/EN/plugins/RadioTime/settings/ Slim/Plugin/RandomPlay/ Slim/Plugin/TT/ Slim/Plugin/xPL/ Slim/Plugin/xPL/HTML/EN/plugins/xPL/settings/ Slim/Utils/ Slim/Utils/Prefs/ Slim/Web/

adrian at svn.slimdevices.com adrian at svn.slimdevices.com
Wed Apr 11 07:56:30 PDT 2007


Author: adrian
Date: Wed Apr 11 07:56:30 2007
New Revision: 11744

URL: http://svn.slimdevices.com?rev=11744&view=rev
Log:
Bug: N/A
Description: initial checkin of preferences supporting namespaces.
New object based preferences + migration of the following plugins to
use it: CLI, DateTime, Podcast, Favorites, xPL, RandomPlay, RadioTime

See Slim::Utils::Prefs for details of new preference class.

At this point all server preferences and remaining plugins use the
previous preference scheme.

Added:
    trunk/server/Slim/Utils/Prefs/
    trunk/server/Slim/Utils/Prefs/Base.pm   (with props)
    trunk/server/Slim/Utils/Prefs/Client.pm   (with props)
    trunk/server/Slim/Utils/Prefs/Namespace.pm   (with props)
    trunk/server/Slim/Utils/Prefs/OldPrefs.pm   (with props)
Modified:
    trunk/server/Slim/Control/Request.pm
    trunk/server/Slim/Plugin/CLI/Plugin.pm
    trunk/server/Slim/Plugin/CLI/Settings.pm
    trunk/server/Slim/Plugin/DateTime/HTML/EN/plugins/DateTime/settings/basic.html
    trunk/server/Slim/Plugin/DateTime/Plugin.pm
    trunk/server/Slim/Plugin/DateTime/Settings.pm
    trunk/server/Slim/Plugin/Favorites/HTML/EN/plugins/Favorites/settings/basic.html
    trunk/server/Slim/Plugin/Favorites/OpmlFavorites.pm
    trunk/server/Slim/Plugin/Favorites/Plugin.pm
    trunk/server/Slim/Plugin/Favorites/Settings.pm
    trunk/server/Slim/Plugin/Podcast/HTML/EN/plugins/Podcast/settings/basic.html
    trunk/server/Slim/Plugin/Podcast/Plugin.pm
    trunk/server/Slim/Plugin/Podcast/Settings.pm
    trunk/server/Slim/Plugin/Podcast/strings.txt
    trunk/server/Slim/Plugin/RadioTime/HTML/EN/plugins/RadioTime/settings/basic.html
    trunk/server/Slim/Plugin/RadioTime/Plugin.pm
    trunk/server/Slim/Plugin/RadioTime/Settings.pm
    trunk/server/Slim/Plugin/RandomPlay/Plugin.pm
    trunk/server/Slim/Plugin/TT/Prefs.pm
    trunk/server/Slim/Plugin/xPL/HTML/EN/plugins/xPL/settings/basic.html
    trunk/server/Slim/Plugin/xPL/Plugin.pm
    trunk/server/Slim/Plugin/xPL/Settings.pm
    trunk/server/Slim/Utils/Log.pm
    trunk/server/Slim/Utils/Prefs.pm
    trunk/server/Slim/Web/Settings.pm
    trunk/server/slimserver.pl
    trunk/server/strings.txt

Modified: trunk/server/Slim/Control/Request.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Control/Request.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Control/Request.pm (original)
+++ trunk/server/Slim/Control/Request.pm Wed Apr 11 07:56:30 2007
@@ -589,6 +589,7 @@
     addDispatch(['playlist',       'cant_open',      '_url'],                                          [1, 0, 0, undef]);
     addDispatch(['rescan',         'done'],                                                            [0, 0, 0, undef]);
     addDispatch(['unknownir',      '_ircode',        '_time'],                                         [1, 0, 0, undef]);
+    addDispatch(['prefset'],                                                                           [0, 0, 1, undef]);
 
 # DEPRECATED
 	addDispatch(['mode',           'pause'],                                                           [1, 0, 0, \&Slim::Control::Commands::playcontrolCommand]);

Modified: trunk/server/Slim/Plugin/CLI/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/CLI/Plugin.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/CLI/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/CLI/Plugin.pm Wed Apr 11 07:56:30 2007
@@ -17,6 +17,7 @@
 use Slim::Utils::Log;
 use Slim::Utils::Misc;
 use Slim::Utils::Unicode;
+use Slim::Utils::Prefs;
 
 # This plugin provides a command-line interface to the server via a TCP/IP port.
 # See cli-api.html for documentation.
@@ -59,6 +60,8 @@
 	'description'  => 'PLUGIN_CLI',
 });
 
+my $prefs = preferences('cli');
+
 ################################################################################
 # PLUGIN CODE
 ################################################################################
@@ -67,12 +70,6 @@
 sub initPlugin {
 
 	$log->info("Initializing");
-
-	# make sure we have a default value for our preference
-	if (!defined Slim::Utils::Prefs::get('cliport')) {
-
-		Slim::Utils::Prefs::set('cliport', 9090);
-	}
 
 	Slim::Plugin::CLI::Settings->new;
 
@@ -175,7 +172,7 @@
 	$log->debug("Begin Function");
 
 	# get the port we must use
-	my $newport = Slim::Utils::Prefs::get('cliport');
+	my $newport = $prefs->get('cliport');
 
 	# if the port changed...
 	if ($cli_socket_port != $newport) {

Modified: trunk/server/Slim/Plugin/CLI/Settings.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/CLI/Settings.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/CLI/Settings.pm (original)
+++ trunk/server/Slim/Plugin/CLI/Settings.pm Wed Apr 11 07:56:30 2007
@@ -8,6 +8,17 @@
 use strict;
 use base qw(Slim::Web::Settings);
 
+use Slim::Utils::Prefs;
+
+my $prefs = preferences('cli');
+
+$prefs->migrate(1, sub {
+	$prefs->set('cliport', Slim::Utils::Prefs::OldPrefs->get('cliport') || 9090); 1;
+});
+
+$prefs->setValidate({ 'validator' => 'intlimit', 'low' => 1024, 'high' => 65535 }, 'cliport');
+$prefs->setChange(\&Slim::Plugin::CLI::Plugin::cli_socket_change, 'cliport');
+
 sub name {
 	return 'PLUGIN_CLI';
 }
@@ -16,30 +27,8 @@
 	return 'plugins/CLI/settings/basic.html';
 }
 
-sub handler {
-	 my ($class, $client, $params) = @_;
-
-	my @prefs = qw(
-		cliport
-	);
-
-	for my $pref (@prefs) {
-
-		if ($params->{'saveSettings'}) {
-
-			# XXX - validate port
-			Slim::Utils::Prefs::set($pref, $params->{$pref});
-
-			if ($params->{$pref} != Slim::Utils::Prefs::get($pref)) {
-
-				Slim::Plugin::CLI::Plugin::cli_socket_change();
-			}
-		}
-
-		$params->{'prefs'}->{$pref} = Slim::Utils::Prefs::get($pref);
-	}
-
-	return $class->SUPER::handler($client, $params);
+sub prefs {
+	return ($prefs, 'cliport');
 }
 
 1;

Modified: trunk/server/Slim/Plugin/DateTime/HTML/EN/plugins/DateTime/settings/basic.html
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/DateTime/HTML/EN/plugins/DateTime/settings/basic.html?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/DateTime/HTML/EN/plugins/DateTime/settings/basic.html (original)
+++ trunk/server/Slim/Plugin/DateTime/HTML/EN/plugins/DateTime/settings/basic.html Wed Apr 11 07:56:30 2007
@@ -4,25 +4,25 @@
 		<div class="groupHead">[% "SETUP_GROUP_DATETIME" | string | upper %]</div>
 		<div class="groupDesc">[% "SETUP_GROUP_DATETIME_DESC" | string %]</div>
 
-		<select name="screensaverDateFormat">
+		<select name="dateformat">
 
-		<option value="" [% IF NOT prefs.screensaverTimeFormat %]selected[% END %]>[% "SETUP_GROUP_DATETIME_DEFAULTTIME" | string %]</option>
+		<option value="" [% IF NOT prefs.dateformat %]selected[% END %]>[% "SETUP_GROUP_DATETIME_DEFAULTTIME" | string %]</option>
 
 		[% FOREACH format = dateFormats %]
 
-			<option value="[% format.key %]" [% IF prefs.screensaverDateFormat == format %]selected[% END %]>[% format.value %]</option>
+			<option value="[% format.key %]" [% IF prefs.dateformat == format.key %]selected[% END %]>[% format.value %]</option>
 
 		[% END %]
 
 		</select>
 
-		<select name="screensaverTimeFormat">
+		<select name="timeformat">
 
-		<option value="" [% IF NOT prefs.screensaverTimeFormat %]selected[% END %]>[% "SETUP_GROUP_DATETIME_DEFAULTTIME" | string %]</option>
+		<option value="" [% IF NOT prefs.timeformat %]selected[% END %]>[% "SETUP_GROUP_DATETIME_DEFAULTTIME" | string %]</option>
 
 		[% FOREACH format = timeFormats %]
 
-			<option value="[% format.key %]" [% IF prefs.screensaverTimeFormat == format %]selected[% END %]>[% format.value %]</option>
+			<option value="[% format.key %]" [% IF prefs.timeformat == format.key %]selected[% END %]>[% format.value %]</option>
 
 		[% END %]
 

Modified: trunk/server/Slim/Plugin/DateTime/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/DateTime/Plugin.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/DateTime/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/DateTime/Plugin.pm Wed Apr 11 07:56:30 2007
@@ -11,6 +11,8 @@
 use Slim::Utils::Prefs;
 
 use Slim::Plugin::DateTime::Settings;
+
+my $prefs = preferences('datetime');
 
 sub getDisplayName {
 	return 'PLUGIN_SCREENSAVER_DATETIME';
@@ -32,17 +34,6 @@
 	$class->SUPER::initPlugin();
 
 	Slim::Plugin::DateTime::Settings->new;
-
-	# Default to screensaverDateFormat, screensaverTimeFormat to '' or update from '0'
-	# Having screensaverDateFormat set to '' means that the server wide formats are used
-
-	if (!Slim::Utils::Prefs::get('screensaverDateFormat')) {
-		Slim::Utils::Prefs::set('screensaverDateFormat','')
-	}
-
-	if (!Slim::Utils::Prefs::get('screensaverTimeFormat')) {
-		Slim::Utils::Prefs::set('screensaverTimeFormat','')
-	}
 
 	Slim::Buttons::Common::addSaver(
 		'SCREENSAVER.datetime',
@@ -151,8 +142,8 @@
 	Slim::Buttons::Common::syncPeriodicUpdates($client, int($nextUpdate)) if (($nextUpdate - int($nextUpdate)) > 0.01);
 
 	my $display = {
-		'center' => [ Slim::Utils::DateTime::longDateF(undef,Slim::Utils::Prefs::get('screensaverDateFormat')),
-				  Slim::Utils::DateTime::timeF(undef,Slim::Utils::Prefs::get('screensaverTimeFormat')), ],
+		'center' => [ Slim::Utils::DateTime::longDateF(undef, $prefs->get('dateformat')),
+					  Slim::Utils::DateTime::timeF(undef, $prefs->get('timeformat')) ],
 		'overlay'=> [ ($alarmOn ? $client->symbols('bell') : undef) ],
 		'fonts'  => $fontDef,
 	};

Modified: trunk/server/Slim/Plugin/DateTime/Settings.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/DateTime/Settings.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/DateTime/Settings.pm (original)
+++ trunk/server/Slim/Plugin/DateTime/Settings.pm Wed Apr 11 07:56:30 2007
@@ -8,6 +8,16 @@
 use strict;
 use base qw(Slim::Web::Settings);
 
+use Slim::Utils::Prefs;
+
+my $prefs = preferences('datetime');
+
+$prefs->migrate(1, sub {
+	$prefs->set('timeformat', Slim::Utils::Prefs::OldPrefs->get('screensaverTimeFormat') || '');
+	$prefs->set('dateformat', Slim::Utils::Prefs::OldPrefs->get('screensaverDateFormat') || '');
+	1;
+});
+
 my $timeFormats = Slim::Utils::DateTime::timeFormats();
 
 my $dateFormats = {
@@ -16,35 +26,24 @@
 };
 
 sub name {
-        return 'PLUGIN_SCREENSAVER_DATETIME';
+	return 'PLUGIN_SCREENSAVER_DATETIME';
 }
 
 sub page {
-        return 'plugins/DateTime/settings/basic.html';
+	return 'plugins/DateTime/settings/basic.html';
+}
+
+sub prefs {
+	return ($prefs, qw(timeformat dateformat) );
 }
 
 sub handler {
-        my ($class, $client, $params) = @_;
-
-	my @prefs = qw(
-		screensaverTimeFormat
-		screensaverDateFormat
-	);
-
-	for my $pref (@prefs) {
-
-		if ($params->{'saveSettings'}) {
-
-			Slim::Utils::Prefs::set($pref, $params->{$pref});
-		}
-
-		$params->{'prefs'}->{$pref} = Slim::Utils::Prefs::get($pref);
-        }
+	my ($class, $client, $params) = @_;
 
 	$params->{'timeFormats'} = $timeFormats;
 	$params->{'dateFormats'} = $dateFormats;
 
-        return $class->SUPER::handler($client, $params);
+	return $class->SUPER::handler($client, $params);
 }
 
 1;

Modified: trunk/server/Slim/Plugin/Favorites/HTML/EN/plugins/Favorites/settings/basic.html
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Favorites/HTML/EN/plugins/Favorites/settings/basic.html?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Favorites/HTML/EN/plugins/Favorites/settings/basic.html (original)
+++ trunk/server/Slim/Plugin/Favorites/HTML/EN/plugins/Favorites/settings/basic.html Wed Apr 11 07:56:30 2007
@@ -6,7 +6,7 @@
 		<div class="prefDesc">[% "PLUGIN_FAVORITES_PLAYLIST_EDITOR_DESC" | string %]</div>
 
 		<div class="prefDesc">[% "ENABLE" | string %]
-		<input name="opmleditor" type="checkbox" [% IF opmleditor %] checked [% END %]>
+		<input name="opmleditor" type="checkbox" [% IF prefs.opmleditor %] checked [% END %]>
 		</div>
 	</div>
 

Modified: trunk/server/Slim/Plugin/Favorites/OpmlFavorites.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Favorites/OpmlFavorites.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Favorites/OpmlFavorites.pm (original)
+++ trunk/server/Slim/Plugin/Favorites/OpmlFavorites.pm Wed Apr 11 07:56:30 2007
@@ -93,8 +93,8 @@
 
 	$log->info("No opml favorites file found - loading old favorites");
 
-	my @urls   = Slim::Utils::Prefs::getArray('favorite_urls');
-	my @titles = Slim::Utils::Prefs::getArray('favorite_titles');
+	my @urls   = @{Slim::Utils::Prefs::OldPrefs->get('favorite_urls')};
+	my @titles = @{Slim::Utils::Prefs::OldPrefs->get('favorite_titles')};
 
 	while (@urls) {
 

Modified: trunk/server/Slim/Plugin/Favorites/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Favorites/Plugin.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Favorites/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/Favorites/Plugin.pm Wed Apr 11 07:56:30 2007
@@ -25,6 +25,7 @@
 use Slim::Utils::Misc;
 use Slim::Utils::Strings qw(string);
 use Slim::Music::Info;
+use Slim::Utils::Prefs;
 
 use Slim::Plugin::Favorites::Opml;
 use Slim::Plugin::Favorites::OpmlFavorites;
@@ -32,6 +33,8 @@
 use Slim::Plugin::Favorites::Playlist;
 
 my $log = logger('favorites');
+
+my $prefs = preferences('favorites');
 
 sub initPlugin {
 	my $class = shift;
@@ -118,7 +121,7 @@
 }
 
 sub addEditLink {
-	my $enabled = Slim::Utils::Prefs::get('plugin_favorites_opmleditor');
+	my $enabled = $prefs->get('opmleditor');
 
 	Slim::Web::Pages->addPageLinks('plugins', {	'PLUGIN_FAVORITES_PLAYLIST_EDITOR' => $enabled ? 'plugins/Favorites/index.html?new' : undef });
 }

Modified: trunk/server/Slim/Plugin/Favorites/Settings.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Favorites/Settings.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Favorites/Settings.pm (original)
+++ trunk/server/Slim/Plugin/Favorites/Settings.pm Wed Apr 11 07:56:30 2007
@@ -8,6 +8,10 @@
 use strict;
 use base qw(Slim::Web::Settings);
 
+use Slim::Utils::Prefs;
+
+my $prefs = preferences('favorites');
+
 sub name {
 	return 'FAVORITES';
 }
@@ -16,21 +20,21 @@
 	return 'plugins/Favorites/settings/basic.html';
 }
 
+sub prefs {
+	return ($prefs, 'opmleditor');
+}
+
 sub handler {
 	my ($class, $client, $params) = @_;
 
+	my $ret = $class->SUPER::handler($client, $params);
+
 	if ($params->{'saveSettings'}) {
-
-		Slim::Utils::Prefs::set('plugin_favorites_opmleditor', exists $params->{'opmleditor'});
 
 		Slim::Plugin::Favorites::Plugin::addEditLink();
 	}
 
-	$params->{'opmleditor'} = Slim::Utils::Prefs::get('plugin_favorites_opmleditor');
-
-	delete $params->{'playerid'};
-
-	return $class->SUPER::handler($client, $params);
+	return $ret;
 }
 
 1;

Modified: trunk/server/Slim/Plugin/Podcast/HTML/EN/plugins/Podcast/settings/basic.html
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Podcast/HTML/EN/plugins/Podcast/settings/basic.html?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Podcast/HTML/EN/plugins/Podcast/settings/basic.html (original)
+++ trunk/server/Slim/Plugin/Podcast/HTML/EN/plugins/Podcast/settings/basic.html Wed Apr 11 07:56:30 2007
@@ -9,19 +9,21 @@
 			<tr>
 			<td><label for="new_feed" class="stdlabel">[% "SETUP_PLUGIN_PODCAST_ADD_FEED" | string %]</label></td>
 
-			<td><input type="text" class="stdedit" name="plugin_podcast_feeds" id="new_feed" value="" size="60" /></td>
+			<td><input type="text" class="stdedit" name="newfeed" value="[% newfeedval %]" size="60" /></td>
 			</tr>
 
 			<tr></tr>
 			<tr></tr>
-			<tr><td><label>[% "SETUP_PLUGIN_PODCAST_EXISTING_FEEDS" | string %]</label></td><td></td></tr>
+			<tr><td><label>[% "SETUP_PLUGIN_PODCAST_EXISTING_FEEDS" | string %]</label></td><td></td><td>[% "DELETE" | string %]</td></tr>
 
 		[% FOREACH pref = prefs %]
 
 			<tr>
-			<td><label for="plugin_podcast_feeds" class="stdlabel">[% pref.1 %]</label></td>
+			<td><label for="feeds" class="stdlabel">[% pref.1 %]</label></td>
 
-			<td><input type="text" class="stdedit" name="plugin_podcast_feeds" id="plugin_podcast_feeds" value="[% pref.0 %]" size="60" /></td>
+			<td><label for="urls"  class="stdlabel">[% pref.0 %]</label></td>
+
+			<td><input name="delete" type="checkbox" value="[% pref.0 %]"></td>
 
 			</tr>
 

Modified: trunk/server/Slim/Plugin/Podcast/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Podcast/Plugin.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Podcast/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/Podcast/Plugin.pm Wed Apr 11 07:56:30 2007
@@ -11,18 +11,15 @@
 use strict;
 use base qw(Slim::Plugin::Base);
 
-use constant FEEDS_VERSION => 1;
-
 use HTML::Entities;
 use XML::Simple;
 
-use Slim::Plugin::Podcast::Settings;
-
 use Slim::Formats::XML;
 use Slim::Utils::Cache;
-use Slim::Utils::Log;
 use Slim::Utils::Misc;
 use Slim::Utils::Strings qw(string);
+use Slim::Utils::Log;
+use Slim::Utils::Prefs;
 
 my $log = Slim::Utils::Log->addLogCategory({
 	'category'     => 'plugin.podcast',
@@ -30,25 +27,10 @@
 	'description'  => getDisplayName(),
 });
 
-# default can be overridden by prefs.  See initPlugin()
-# TODO: come up with a better list of defaults.
-our @default_feeds = (
-	{
-		name => 'Odeo',
-		value => 'http://content.us.squeezenetwork.com:8080/opml/odeo.opml',
-	},
-	{
-		name => 'PodcastAlley Top 50',
-		value => 'http://podcastalley.com/PodcastAlleyTop50.opml'
-	},
-	{
-		name => 'PodcastAlley 10 Newest',
-		value => 'http://podcastalley.com/PodcastAlley10Newest.opml'
-	},
-);
-
-our @feeds = ();
-our %feed_names; # cache of feed names
+my $prefs = preferences('podcast');
+
+use Slim::Plugin::Podcast::Settings;
+
 my $cli_next;
 
 sub initPlugin {
@@ -61,13 +43,6 @@
 	$class->SUPER::initPlugin();
 
 	Slim::Buttons::Common::addMode('PLUGIN.Podcast', getFunctions(), \&setMode);
-
-	my @feedURLPrefs = Slim::Utils::Prefs::getArray("plugin_podcast_feeds");
-	my @feedNamePrefs = Slim::Utils::Prefs::getArray("plugin_podcast_names");
-	my $feedsModified = Slim::Utils::Prefs::get("plugin_podcast_feeds_modified");
-	my $version = Slim::Utils::Prefs::get("plugin_podcast_feeds_version");
-
-	@feeds = ();
 
 #        |requires Client
 #        |  |is a Query
@@ -81,33 +56,11 @@
 	$cli_next=Slim::Control::Request::addDispatch(['radios', '_index', '_quantity' ],
 		[0, 1, 1, \&cliRadiosQuery]);
 
-
-	# 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
-		for (my $i = 0; $i < scalar(@feedNamePrefs); $i++) {
-
-			push @feeds, {
-				name  => $feedNamePrefs[$i],
-				value => $feedURLPrefs[$i],
-				type  => 'link',
-			};
-		}
-	}
-
 	if ($log->is_debug) {
 
 		$log->debug("Feed Info:");
 
-		for my $feed (@feeds) {
+		for my $feed (@{$prefs->get('feeds')}) {
 
 			$log->debug(join(', ', $feed->{'name'}, $feed->{'value'}));
 		}
@@ -115,20 +68,7 @@
 		$log->debug('');
 	}
 
-	updateOPMLCache( \@feeds );
-}
-
-sub revertToDefaults {
-	@feeds = @default_feeds;
-
-	my @urls  = map { $_->{'value'}} @feeds;
-	my @names = map { $_->{'name'}} @feeds;
-
-	Slim::Utils::Prefs::set('plugin_podcast_feeds', \@urls);
-	Slim::Utils::Prefs::set('plugin_podcast_names', \@names);
-	Slim::Utils::Prefs::set('plugin_podcast_feeds_version', FEEDS_VERSION);
-
-	updateOPMLCache( \@feeds );
+	updateOPMLCache( $prefs->get('feeds') );
 }
 
 sub getDisplayName {
@@ -152,7 +92,7 @@
 	# use INPUT.Choice to display the list of feeds
 	my %params = (
 		header => '{PLUGIN_PODCAST} {count}',
-		listRef => \@feeds,
+		listRef => $prefs->get('feeds'),
 		modeName => 'Podcast Plugin',
 		onRight => sub {
 			my $client = shift;
@@ -238,11 +178,6 @@
 sub updateOPMLCache {
 	my $feeds = shift;
 
-	# feed_names should reflect current names
-	%feed_names = ();
-
-	map { $feed_names{$_->{'value'}} = $_->{'name'} } @feeds;
-	
 	my $outline = [];
 
 	for my $item ( @{$feeds} ) {
@@ -250,7 +185,7 @@
 			'name'  => $item->{'name'},
 			'url'   => $item->{'value'},
 			'value' => $item->{'value'},
-			'type'  => $item->{'type'},
+			'type'  => $item->{'type'} || 'lnk',
 			'items' => [],
 		};
 	}
@@ -266,85 +201,4 @@
 	$cache->set( 'podcasts_opml', $opml, '10days' );
 }
 
-sub updateFeedNames {
-	my @feedURLPrefs  = Slim::Utils::Prefs::getArray("plugin_podcast_feeds");
-	my @feedNamePrefs = ();
-
-	# verbose debug
-	if ($log->is_debug) {
-
-		$log->debug("URLs: " . Data::Dump::dump(\@feedURLPrefs));
-	}
-
-	# case 1: we're reverting to default
-	if (scalar(@feedURLPrefs) == 0) {
-
-		revertToDefaults();
-		return;
-	}
-
-	# 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
-			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_podcast_names', \@feedNamePrefs);
-
-	# runtime list must reflect changes
-	@feeds = ();
-
-	for (my $i = 0; $i < scalar(@feedNamePrefs); $i++) {
-
-		push @feeds, {
-			name  => $feedNamePrefs[$i],
-			value => $feedURLPrefs[$i],
-			type  => 'link',
-		};
-	}
-
-	updateOPMLCache( \@feeds );
-}
-
 1;

Modified: trunk/server/Slim/Plugin/Podcast/Settings.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Podcast/Settings.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Podcast/Settings.pm (original)
+++ trunk/server/Slim/Plugin/Podcast/Settings.pm Wed Apr 11 07:56:30 2007
@@ -7,6 +7,51 @@
 
 use strict;
 use base qw(Slim::Web::Settings);
+
+use Slim::Utils::Log;
+use Slim::Utils::Prefs;
+
+my $log   = logger('plugin.podcast');
+my $prefs = preferences('podcast');
+
+use constant FEED_VERSION => 2; # bump this number when changing the defaults below
+
+our @default_feeds = (
+	{
+		name  => 'Odeo',
+		value => 'http://content.us.squeezenetwork.com:8080/opml/odeo.opml',
+	},
+	{
+		name  => 'PodcastAlley Top 50',
+		value => 'http://podcastalley.com/PodcastAlleyTop50.opml'
+	},
+	{
+		name  => 'PodcastAlley 10 Newest',
+		value => 'http://podcastalley.com/PodcastAlley10Newest.opml'
+	},
+);
+
+# migrate old prefs across
+$prefs->migrate(1, sub {
+	my @names  = @{Slim::Utils::Prefs::OldPrefs->get('plugin_podcast_names')};
+	my @values = @{Slim::Utils::Prefs::OldPrefs->get('plugin_podcast_feeds')};
+	my @feeds;
+
+	for my $name (@names) {
+		push @feeds, { 'name' => $name, 'value' => shift @values };
+	}
+
+	if (@feeds) {
+		$prefs->set('feeds', \@feeds);
+		$prefs->set('modified', 1);
+	}
+});
+
+# migrate to latest version of default feeds if they have not been modified
+$prefs->migrate(FEED_VERSION, sub {
+	$prefs->set('feeds', \@default_feeds) unless $prefs->get('modified');
+	1;
+});
 
 sub name {
 	return 'PLUGIN_PODCAST';
@@ -20,30 +65,88 @@
 	my ($class, $client, $params) = @_;
 
 	if ($params->{'reset'}) {
-		Slim::Plugin::Podcast::Plugin::revertToDefaults();
+
+		$prefs->set('feeds', \@default_feeds);
+		$prefs->set('modified', 0);
+
+		Slim::Plugin::Podcast::Plugin::updateOPMLCache(\@default_feeds);
 	}
 
 	if ($params->{'saveSettings'}) {
 
-		# Remove empty feeds.
-		my @feeds = grep { $_ ne '' } @{$params->{'plugin_podcast_feeds'}};
+		my @feeds       = @{ $prefs->get('feeds') };
+		my $newFeedUrl  = $params->{'newfeed'};
+		my $newFeedName = validateFeed($newFeedUrl);
 
-		Slim::Utils::Prefs::set('plugin_podcast_feeds', \@feeds);
+		if ($newFeedUrl && $newFeedName) {
 
-		Slim::Plugin::Podcast::Plugin::updateFeedNames();
+			push @feeds, {
+				'name'  => $newFeedName,
+				'value' => $newFeedUrl,
+			};
+
+		} elsif ($newFeedUrl) {
+
+			$params->{'warning'} .= sprintf Slim::Utils::Strings::string('SETUP_PLUGIN_PODCAST_INVALID_FEED'), $newFeedUrl;
+			$params->{'newfeedval'} = $params->{'newfeed'};
+		}
+
+		my @delete = @{ ref $params->{'delete'} eq 'ARRAY' ? $params->{'delete'} : [ $params->{'delete'} ] };
+
+		for my $deleteItem (@delete) {
+			my $i = 0;
+			while ($i < scalar @feeds) {
+				if ($deleteItem eq $feeds[$i]->{'value'}) {
+					splice @feeds, $i, 1;
+					next;
+				}
+				$i++;
+			}
+		}
+
+		$prefs->set('feeds', \@feeds);
+		$prefs->set('modified', 1);
+
+		Slim::Plugin::Podcast::Plugin::updateOPMLCache(\@feeds);
 	}
 
-	my @feeds = Slim::Utils::Prefs::getArray('plugin_podcast_feeds');
-	my @names = Slim::Utils::Prefs::getArray('plugin_podcast_names');
+	for my $feed (@{ $prefs->get('feeds') }) {
 
-	for (my $i = 0; $i < @feeds; $i++) {
-
-		push @{$params->{'prefs'}}, [ $feeds[$i], $names[$i] ];
+		push @{$params->{'prefs'}}, [ $feed->{'value'}, $feed->{'name'} ];
 	}
 
 	return $class->SUPER::handler($client, $params);
 }
 
+sub validateFeed {
+	my $url = shift || return undef;
+
+	$log->info("validating $url");
+
+	# this is synchronous at present
+	my $xml = Slim::Formats::XML->getFeedSync($url);
+
+	if ($xml && exists $xml->{'channel'}->{'title'}) {
+
+		# here for podcasts and RSS
+		return Slim::Formats::XML::unescapeAndTrim($xml->{'channel'}->{'title'});
+
+	} elsif ($xml && exists $xml->{'head'}->{'title'}) {
+
+		# here for OPML
+		return Slim::Formats::XML::unescapeAndTrim($xml->{'head'}->{'title'});
+
+	} elsif ($xml) {
+
+		# got xml but can't find title - use url
+		return $url;
+	}
+
+	$log->warn("unable to connect to $url");
+
+	return undef;
+}
+
 1;
 
 __END__

Modified: trunk/server/Slim/Plugin/Podcast/strings.txt
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/Podcast/strings.txt?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/Podcast/strings.txt (original)
+++ trunk/server/Slim/Plugin/Podcast/strings.txt Wed Apr 11 07:56:30 2007
@@ -62,3 +62,6 @@
 SETUP_PLUGIN_PODCAST_EXISTING_FEEDS
 	DE	Eingetragene Feeds:
 	EN	Existing feeds:
+
+SETUP_PLUGIN_PODCAST_INVALID_FEED
+	EN	Invalid Feed - Can't connect to %s

Modified: trunk/server/Slim/Plugin/RadioTime/HTML/EN/plugins/RadioTime/settings/basic.html
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/RadioTime/HTML/EN/plugins/RadioTime/settings/basic.html?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/RadioTime/HTML/EN/plugins/RadioTime/settings/basic.html (original)
+++ trunk/server/Slim/Plugin/RadioTime/HTML/EN/plugins/RadioTime/settings/basic.html Wed Apr 11 07:56:30 2007
@@ -6,7 +6,7 @@
 		<div class="prefDesc">[% "SETUP_PLUGIN_RADIOTIME_USERNAME_DESC" | string %]</div>
 
 		<div class="prefDesc">[% "SETUP_PLUGIN_RADIOTIME_USERNAME" | string %]</div>
-		<input type="text" class="stdedit" name="plugin_radiotime_username" id="plugin_radiotime_username" value="[% prefs.plugin_radiotime_username %]" size="40">
+		<input type="text" class="stdedit" name="username" id="username" value="[% prefs.username %]" size="40">
 	</div>
 
 [% PROCESS settings/footer.html %]

Modified: trunk/server/Slim/Plugin/RadioTime/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/RadioTime/Plugin.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/RadioTime/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/RadioTime/Plugin.pm Wed Apr 11 07:56:30 2007
@@ -23,6 +23,7 @@
 use Slim::Buttons::XMLBrowser;
 use Slim::Utils::Strings qw( string );
 use Slim::Web::XMLBrowser;
+use Slim::Utils::Prefs;
 
 my $FEED = 'http://opml.radiotime.com/Index.aspx';
 my $cli_next;
@@ -32,6 +33,8 @@
 	'defaultLevel' => 'WARN',
 	'description'  => getDisplayName(),
 });
+
+my $prefs = preferences('radiotime');
 
 sub initPlugin {
 	my $class = shift;
@@ -91,7 +94,7 @@
 		$username = $client->prefGet('plugin_radiotime_username', undef, 1);
 	}
 	else {
-		$username = Slim::Utils::Prefs::get('plugin_radiotime_username');
+		$username = $prefs->get('username');
 	}
 	
 	my $url = $FEED;

Modified: trunk/server/Slim/Plugin/RadioTime/Settings.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/RadioTime/Settings.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/RadioTime/Settings.pm (original)
+++ trunk/server/Slim/Plugin/RadioTime/Settings.pm Wed Apr 11 07:56:30 2007
@@ -8,16 +8,24 @@
 use strict;
 use base qw(Slim::Web::Settings);
 
+use Slim::Utils::Prefs;
+
+my $prefs = preferences('radiotime');
+
+$prefs->migrate(1, sub {
+	$prefs->set('username', Slim::Utils::Prefs::OldPrefs->get('plugin_radiotime_username')); 1;
+});
+
 sub name {
-        return 'PLUGIN_RADIOTIME_MODULE_NAME';
+	return 'PLUGIN_RADIOTIME_MODULE_NAME';
 }
 
 sub page {
-        return 'plugins/RadioTime/settings/basic.html';
+	return 'plugins/RadioTime/settings/basic.html';
 }
 
 sub prefs {
-	return qw(plugin_radiotime_username);
+	return ($prefs, 'username');
 }
 
 1;

Modified: trunk/server/Slim/Plugin/RandomPlay/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/RandomPlay/Plugin.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/RandomPlay/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/RandomPlay/Plugin.pm Wed Apr 11 07:56:30 2007
@@ -21,6 +21,7 @@
 use Slim::Utils::Log;
 use Slim::Utils::Misc;
 use Slim::Utils::Strings qw(string);
+use Slim::Utils::Prefs;
 
 my %stopcommands = ();
 
@@ -41,6 +42,23 @@
 	'defaultLevel' => 'WARN',
 	'description'  => getDisplayName(),
 });
+
+my $prefs = preferences('randomplay');
+
+$prefs->migrate(1, sub {
+	$prefs->set('newtracks', Slim::Utils::Prefs::OldPrefs->get('plugin_random_number_of_tracks')     || 10 );
+	$prefs->set('oldtracks', Slim::Utils::Prefs::OldPrefs->get('plugin_random_number_of_old_tracks') || 0  );
+	$prefs->set('continue',  Slim::Utils::Prefs::OldPrefs->get('plugin_random_keep_adding_tracks')   || 1  );
+	$prefs->set('exclude_genres', Slim::Utils::Prefs::OldPrefs->get('plugin_random_exclude_genres')  || [] );
+	1;
+});
+
+$prefs->migrateClient(1, sub {
+	my ($clientprefs, $client) = @_;
+	$clientprefs->set('type', Slim::Utils::Prefs::OldPrefs->clientGet($client, 'plugin_random_type')); 1;
+});
+
+$prefs->setValidate('int', qw(newtracks oldtracks) );
 
 sub getDisplayName {
 	return 'PLUGIN_RANDOM';
@@ -61,8 +79,6 @@
 		'loadalbum'  => 1, # old style multi-item load
 		'playalbum'  => 1, # old style multi-item play
 	);
-	
-	checkDefaults();
 
 	generateGenreNameMap();
 
@@ -225,7 +241,7 @@
 
 	# Extract each genre name into a hash
 	my %clientGenres = ();
-	my @exclude      = Slim::Utils::Prefs::getArray('plugin_random_exclude_genres');
+	my @exclude      = @{$prefs->get('exclude_genres')};
 
 	while (my $genre = $rs->next) {
 
@@ -310,7 +326,7 @@
 	$type = lc($type);
 
 	# Whether to keep adding tracks after generating the initial playlist
-	my $continuousMode = Slim::Utils::Prefs::get('plugin_random_keep_adding_tracks');
+	my $continuousMode = $prefs->get('continuous');
 
 	# If this is a new mix, store the start time
 	my $startTime = undef;
@@ -319,7 +335,7 @@
 
 		$mixInfo{$client->masterOrSelf->id}->{'idList'} = undef;
 
-		$client->prefSet('plugin_random_type', $type) unless ($type eq 'disable');
+		$prefs->client($client)->set('type', $type) unless ($type eq 'disable');
 
 		$startTime = time() if $continuousMode;
 	}
@@ -335,7 +351,7 @@
 	if ($type eq 'track') {
 
 		# Add new tracks if there aren't enough after the current track
-		my $numRandomTracks = Slim::Utils::Prefs::get('plugin_random_number_of_tracks');
+		my $numRandomTracks = $prefs->get('newtracks');
 
 		if (!$addOnly) {
 
@@ -606,7 +622,7 @@
 		$genres{$client}->{$item->{'name'}}->{'enabled'} = ! $genres{$client}->{$item->{'name'}}->{'enabled'};
 	}
 
-	Slim::Utils::Prefs::set('plugin_random_exclude_genres', getFilteredGenres($client, 1, 1));
+	$prefs->set('exclude_genres', getFilteredGenres($client, 1, 1) );
 
 	$client->update;
 }
@@ -718,7 +734,7 @@
 		return;
 	}
 
-	if (!defined $client || !defined $mixInfo{$client->masterOrSelf->id}->{'type'} || !Slim::Utils::Prefs::get('plugin_random_keep_adding_tracks')) {
+	if (!defined $client || !defined $mixInfo{$client->masterOrSelf->id}->{'type'} || !$prefs->get('continuous')) {
 		return;
 	}
 
@@ -753,9 +769,9 @@
 			}
 		}
 
-		my $songsToKeep = Slim::Utils::Prefs::get('plugin_random_number_of_old_tracks');
-
-		if ($songIndex && $songsToKeep ne '' && $songIndex > $songsToKeep) {
+		my $songsToKeep = $prefs->get('oldtracks'); # 0 = keep all
+
+		if ($songIndex && $songsToKeep && $songIndex > $songsToKeep) {
 
 			$log->info(sprintf("Stripping off %i completed track(s)", $songIndex - $songsToKeep));
 
@@ -835,7 +851,7 @@
 sub buttonStart {
 	my $client = shift;
 
-	playRandom($client, $client->prefGet('plugin_random_type') || 'track');
+	playRandom($client, $prefs->client($client)->get('type') || 'track');
 }
 
 sub webPages {
@@ -856,11 +872,11 @@
 
 	if ($client) {
 		# Pass on the current pref values and now playing info
-		$params->{'pluginRandomGenreList'} = getGenres($client);
-		$params->{'pluginRandomNumTracks'} = Slim::Utils::Prefs::get('plugin_random_number_of_tracks');
-		$params->{'pluginRandomNumOldTracks'} = Slim::Utils::Prefs::get('plugin_random_number_of_old_tracks');
-		$params->{'pluginRandomContinuousMode'} = Slim::Utils::Prefs::get('plugin_random_keep_adding_tracks');
-		$params->{'pluginRandomNowPlaying'} = $mixInfo{$client->masterOrSelf->id}->{'type'};
+		$params->{'pluginRandomGenreList'}     = getGenres($client);
+		$params->{'pluginRandomNumTracks'}     = $prefs->get('newtracks');
+		$params->{'pluginRandomNumOldTracks'}  = $prefs->get('oldtracks') || ''; # convert 0 to ''
+		$params->{'pluginRandomContinuousMode'}= $prefs->get('continuous');
+		$params->{'pluginRandomNowPlaying'}    = $mixInfo{$client->masterOrSelf->id}->{'type'};
 	}
 	
 	return Slim::Web::HTTP::filltemplatefile($htmlTemplate, $params);
@@ -891,67 +907,15 @@
 		}
 	}
 
-	Slim::Utils::Prefs::set('plugin_random_exclude_genres', [keys %{$genres}]);	
-
-	if ($params->{'numTracks'} =~ /^[0-9]+$/) {
-
-		Slim::Utils::Prefs::set('plugin_random_number_of_tracks', $params->{'numTracks'});
-
-	} else {
-
-		$log->warn("Warning: Invalid value for numTracks");
-	}
-
-	if ($params->{'numOldTracks'} eq '' || $params->{'numOldTracks'} =~ /^[0-9]+$/) {
-
-		Slim::Utils::Prefs::set('plugin_random_number_of_old_tracks', $params->{'numOldTracks'});	
-
-	} else {
-
-		$log->warn("Warning: Invalid value for numOldTracks");
-	}
-
-	Slim::Utils::Prefs::set('plugin_random_keep_adding_tracks', $params->{'continuousMode'} ? 1 : 0);
+	$prefs->set('exclude_genres', [keys %{$genres}]);
+ 	$prefs->set('newtracks', $params->{'numTracks'});
+ 	$prefs->set('oldtracks', $params->{'numOldTracks'} || 0); # convert '' to 0
+	$prefs->set('continuous', $params->{'continuousMode'} ? 1 : 0);
 
 	# Pass on to check if the user requested a new mix as well
 	handleWebMix($client, $params);
 }
 
-sub checkDefaults {
-	my $prefVal = Slim::Utils::Prefs::get('plugin_random_number_of_tracks');
-
-	if (! defined $prefVal || $prefVal !~ /^[0-9]+$/) {
-
-		$log->debug("Defaulting plugin_random_number_of_tracks to 10");
-
-		Slim::Utils::Prefs::set('plugin_random_number_of_tracks', 10);
-	}
-	
-	$prefVal = Slim::Utils::Prefs::get('plugin_random_number_of_old_tracks');
-
-	if (! defined $prefVal || $prefVal !~ /^$|^[0-9]+$/) {
-
-		# Default to keeping all tracks
-		$log->debug("Defaulting plugin_random_number_of_old_tracks to ''");
-
-		Slim::Utils::Prefs::set('plugin_random_number_of_old_tracks', '');
-	}
-
-	if (! defined Slim::Utils::Prefs::get('plugin_random_keep_adding_tracks')) {
-
-		# Default to continous mode
-		$log->debug("Defaulting plugin_random_keep_adding_tracks to 1");
-
-		Slim::Utils::Prefs::set('plugin_random_keep_adding_tracks', 1);
-	}
-
-	if (!Slim::Utils::Prefs::isDefined('plugin_random_exclude_genres')) {
-
-		# Include all genres by default
-		Slim::Utils::Prefs::set('plugin_random_exclude_genres', []);
-	}
-}
-
 sub active {
 	my $client = shift;
 

Modified: trunk/server/Slim/Plugin/TT/Prefs.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/TT/Prefs.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/TT/Prefs.pm (original)
+++ trunk/server/Slim/Plugin/TT/Prefs.pm Wed Apr 11 07:56:30 2007
@@ -6,33 +6,23 @@
 # modify it under the terms of the GNU General Public License, 
 # version 2.
 
+# TT wrapper to access prefs, e.g of use:
+#
+# [% USE Prefs; FOREACH namespace = Prefs.namespaces %] <h3>[% namespace %]</h3>
+# [% prefs = Prefs.preferences(namespace) %]
+# [% FOREACH pref = prefs.all.keys %] [% pref %] = [% prefs.get(pref) %]<br>[% END %]
+# [% END %]
+
 use strict;
 use base qw(Template::Plugin);
 
-sub load {
-	my ($class, $context) = @_;
-
-	return $class;
+sub namespaces {
+	return Slim::Utils::Prefs::namespaces();
 }
 
-sub new {
-	my ($class, $context, @params) = @_;
-	bless {}, $class;
-}
-
-sub get {
+sub preferences {
 	my $self = shift;
-	return Slim::Utils::Prefs::get(@_);
-}
-
-sub getInd {
-	my $self = shift;
-	return Slim::Utils::Prefs::getInd(@_);
-}
-
-sub clientGet {
-	my $self = shift;
-	return Slim::Utils::Prefs::clientGet(@_);
+	return Slim::Utils::Prefs::preferences(@_);
 }
 
 1;

Modified: trunk/server/Slim/Plugin/xPL/HTML/EN/plugins/xPL/settings/basic.html
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/xPL/HTML/EN/plugins/xPL/settings/basic.html?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/xPL/HTML/EN/plugins/xPL/settings/basic.html (original)
+++ trunk/server/Slim/Plugin/xPL/HTML/EN/plugins/xPL/settings/basic.html Wed Apr 11 07:56:30 2007
@@ -9,19 +9,19 @@
 		<tr>
 			<td><label for="xplinterval">[% "SETUP_XPLINTERVAL_CHOOSE" | string %]</label></td>
 			<td>
-				<input type="text" class="stdedit" name="xplinterval" id="xplinterval" value="[% prefs.xplinterval %]" size="5">
+				<input type="text" class="stdedit" name="interval" id="xplinterval" value="[% prefs.interval %]" size="5">
 			</td>
 		</tr>
 
 		<tr>
 			<td><label for="xplir">[% "SETUP_XPLIR_CHOOSE" | string %]</label></td>
 			<td>
-				<select name="xplir">
+				<select name="ir">
 
-				<option value="none" [% IF prefs.xplir == "none" %]selected[% END %]>[% "SETUP_XPLIR_NONE" | string %]</option>
-				<option value="buttons" [% IF prefs.xplir == "buttons" %]selected[% END %]>[% "SETUP_XPLIR_BUTTONS" | string %]</option>
-				<option value="raw" [% IF prefs.xplir == "raw" %]selected[% END %]>[% "SETUP_XPLIR_RAW" | string %]</option>
-				<option value="both" [% IF prefs.xplir == "both" %]selected[% END %]>[% "SETUP_XPLIR_BOTH" | string %]</option>
+				<option value="none" [% IF prefs.ir == "none" %]selected[% END %]>[% "SETUP_XPLIR_NONE" | string %]</option>
+				<option value="buttons" [% IF prefs.ir == "buttons" %]selected[% END %]>[% "SETUP_XPLIR_BUTTONS" | string %]</option>
+				<option value="raw" [% IF prefs.ir == "raw" %]selected[% END %]>[% "SETUP_XPLIR_RAW" | string %]</option>
+				<option value="both" [% IF prefs.ir == "both" %]selected[% END %]>[% "SETUP_XPLIR_BOTH" | string %]</option>
 
 				</select>
 			</td>

Modified: trunk/server/Slim/Plugin/xPL/Plugin.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/xPL/Plugin.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/xPL/Plugin.pm (original)
+++ trunk/server/Slim/Plugin/xPL/Plugin.pm Wed Apr 11 07:56:30 2007
@@ -41,6 +41,8 @@
 	'description'  => getDisplayName(),
 });
 
+my $prefs = preferences('xpl');
+
 ################################################################################
 # PLUGIN CODE
 ################################################################################
@@ -54,19 +56,7 @@
 
 	$localip = inet_ntoa((gethostbyname($computername))[4]);
 
-	$xpl_interval =	Slim::Utils::Prefs::get("xplinterval");
-
-	if (!defined($xpl_interval)) {
-		$xpl_interval = 5;
-		Slim::Utils::Prefs::set("xplinterval",$xpl_interval);
-	}
-
-	$xpl_ir = Slim::Utils::Prefs::get("xplir");
-
-	if (!defined($xpl_ir)) {
-		$xpl_ir = 'none'; 
-		Slim::Utils::Prefs::set("xplir",$xpl_ir);
-	}
+	$xpl_interval =	$prefs->get('interval');
 
 	$xpl_port = 50000;
 
@@ -541,8 +531,8 @@
 		$xpl_ir = $new_ir;
 	}
 
-	Slim::Utils::Prefs::set("xplinterval",$xpl_interval);
-	Slim::Utils::Prefs::set("xplir",$xpl_ir);
+	$prefs->set('interval', $xpl_interval);
+	$prefs->set('ir', $xpl_ir);
 	sendXplHBeatMsg($client);
 }
 

Modified: trunk/server/Slim/Plugin/xPL/Settings.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Plugin/xPL/Settings.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Plugin/xPL/Settings.pm (original)
+++ trunk/server/Slim/Plugin/xPL/Settings.pm Wed Apr 11 07:56:30 2007
@@ -8,17 +8,26 @@
 use strict;
 use base qw(Slim::Web::Settings);
 
+use Slim::Utils::Prefs;
+
+my $prefs = preferences('xpl');
+
+$prefs->migrate(1, sub {
+	$prefs->set('interval', Slim::Utils::Prefs::OldPrefs->get('xplinterval') || 5);
+	$prefs->set('ir', Slim::Utils::Prefs::OldPrefs->get('xplir') || 'none');
+	1;
+});
+
 sub name {
-        return 'PLUGIN_XPL';
+	return 'PLUGIN_XPL';
 }
 
 sub page {
-        return 'plugins/xPL/settings/basic.html';
+	return 'plugins/xPL/settings/basic.html';
 }
 
 sub prefs {
-
-	return qw(xplinterval xplir);
+	return ($prefs, qw(interval ir) );
 }
 
 1;

Modified: trunk/server/Slim/Utils/Log.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Utils/Log.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Utils/Log.pm (original)
+++ trunk/server/Slim/Utils/Log.pm Wed Apr 11 07:56:30 2007
@@ -627,11 +627,11 @@
 sub defaultConfigFile {
 	my $class = shift;
 
-	my $cacheDir = Slim::Utils::Prefs::get('cachedir');
-
-	if (defined $cacheDir && -d $cacheDir) {
-
-		return File::Spec->catdir($cacheDir, 'log.conf');
+	my $logDir = Slim::Utils::OSDetect::dirsFor('log');
+
+	if (defined $logDir && -d $logDir) {
+
+		return File::Spec->catdir($logDir, 'log.conf');
 	}
 }
 

Modified: trunk/server/Slim/Utils/Prefs.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Utils/Prefs.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Utils/Prefs.pm (original)
+++ trunk/server/Slim/Utils/Prefs.pm Wed Apr 11 07:56:30 2007
@@ -34,10 +34,11 @@
 
 my $DEFAULT_DBSOURCE = 'dbi:mysql:hostname=127.0.0.1;port=9092;database=%s';
 
-# Prefs is special - we need to be loaded before logging, but use logging later on.
-my $log = undef;
+my $log = logger('prefs');
 
 sub init {
+
+	init_new();
 
 	# These are scripts that are run once on old prefs file to bring them
 	# up-to-date with specific changes we want to push out to default prefs.
@@ -1231,6 +1232,113 @@
 	close(NUPREFS);	
 }	
 
+
+########################################################################################################
+# new object based preferences - some of above will migrate to use these, both used during migration
+########################################################################################################
+
+=head1 NAME
+
+Slim::Utils::Prefs
+
+=head1 SYNOPSIS
+
+use Slim::Utils::Pres;
+
+my $prefs = preferences('demo');
+
+$prefs->set('pref1', 1); or $prefs->pref1(1);
+
+$prefs->get('pref1'); or $prefs->pref1;
+
+$prefs->client($client)->set('clientpref1', 1); or $prefs->client($client)->clientpref1(1);
+
+$prefs->client($client)->get('clientpref1'); or $prefs->client($client)->clientpref1;
+
+$prefs->init({ 'pref1' => 1, 'pref2' => 2 });
+
+$pref->remove( 'pref1' );
+
+$prefs->migrate(1, sub {
+	$prefs->set('skin', Slim::Utils::Prefs::OldPrefs->get('skin') );
+	1;
+});
+
+$prefs->setValidate('int', 'pref1');
+
+$prefs->setChange(\&myCallback, 'pref1');
+
+=head1 DESCRIPTION
+
+Object based preferences supporing multiple namespaces so the server and
+each plugin can have their own preference namespace.
+Supports both global and client preferences within a namespace.
+
+This implementation stores preferences in YAML files with one YAML file per namespace.
+
+=head2 Each preference may be associated with:
+
+=item validation function to verify the new value for a preference before setting it
+
+=item on change callback to execute when a preference is set
+
+=head2 Each namespace supports:
+
+=item migration functions to update preferences to a new version number
+(each namespace has a global and per client version number)
+
+=head2 SEE ALSO
+
+L<Slim::Utils::Prefs::Base>
+L<Slim::Utils::Prefs::Namespace>
+L<Slim::Utils::Prefs::Client>
+L<Slim::Utils::Preds::OldPrefs>
+
+=cut
+
+use Slim::Utils::Prefs::Namespace;
+use Slim::Utils::Prefs::OldPrefs;
+
+use Exporter::Lite;
+
+our @EXPORT = qw(preferences);
+
+my $path = Slim::Utils::OSDetect::dirsFor('prefs');
+
+my $prefs = preferences('server');
+
+my %namespaces;
+
+sub preferences {
+	my $namespace = shift;
+
+	return $namespaces{$namespace} ||= Slim::Utils::Prefs::Namespace->new($namespace, $path);
+}
+
+sub init_new {
+	$prefs->migrate(1, sub {
+		unless (-d $path) {
+			mkdir $path;
+		}
+
+		unless (-d $path) {
+			logError("can't create new preferences directory at $path");
+		}
+
+		0;
+	});
+}
+
+sub namespaces {
+	return [ keys %namespaces ];
+}
+
+sub writeAll {
+	for my $n (values %namespaces) {
+		$n->savenow;
+	}
+}
+
 1;
 
 __END__

Added: trunk/server/Slim/Utils/Prefs/Base.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Utils/Prefs/Base.pm?rev=11744&view=auto
==============================================================================
--- trunk/server/Slim/Utils/Prefs/Base.pm (added)
+++ trunk/server/Slim/Utils/Prefs/Base.pm Wed Apr 11 07:56:30 2007
@@ -1,0 +1,203 @@
+package Slim::Utils::Prefs::Base;
+
+# $Id$
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License, 
+# version 2.
+
+=head1 NAME
+
+Slim::Utils::Prefs::Base
+
+=head1 DESCRIPTION
+
+Base class for preference objects implementing methods which can be used on global and client preferences.
+
+=head1 METHODS
+
+=cut
+
+use strict;
+
+use Scalar::Util qw(blessed);
+
+use Slim::Utils::Log;
+
+my $optimiseAccessors = 1;
+
+my $log = logger('prefs');
+
+=head2 get( $prefname )
+
+Returns the current value of preference $prefname.
+
+(A preference value may also be accessed using $prefname as an accessor method.)
+
+=cut
+
+sub get {
+	shift->{'prefs'}->{ $_[0] };
+}
+
+=head2 exists( $prefname )
+
+Returns whether preference $prefname exists.
+
+=cut
+
+sub exists {
+	exists shift->{'prefs'}->{ $_[0] };
+}
+
+=head2 set( $prefname, $value )
+
+Sets preference $prefname to $value.
+
+If a validator is set for this $prefname this is checked first.  If an on change callback is set this is called
+after setting the preference.
+
+NB preferences only store scalar values.  Hashes or Arrays should be stored as references.
+
+(A preference may also be set $prefname as an accessor method.)
+
+=cut
+
+sub set {
+	my $class = shift;
+	my $pref  = shift;
+	my $new   = shift;
+
+	my $old   = $class->{'prefs'}->{ $pref };
+
+	my $root  = $class->_root;
+	my $change = $root->{'onchange'}->{ $pref };
+	my $validator = $root->{'validators'}->{ $pref };
+	my $namespace = $root->{'namespace'};
+	my $clientid  = $class->{'clientid'} || '';
+
+	my $valid  = $validator ? $validator->($pref, $new, $root->{'validparams'}->{ $pref }, $old, $class->_obj) : 1;
+
+	if ($valid && $pref !~ /^_/) {
+
+		$log->debug(sprintf "setting %s:%s:%s to %s", $namespace, $clientid, $pref, defined $new ? $new : 'undef');
+
+		$class->{'prefs'}->{ $pref } = $new;
+
+		$root->save;
+
+		if ($change) {
+			$change->($pref, $new, $class->_obj);
+		}
+
+		Slim::Control::Request::notifyFromArray(Slim::Player::Client::getClient($clientid), ['prefset', $namespace, $pref, $new]);
+
+		return wantarray ? ($new, 1) : $new;
+
+	} else {
+
+		$log->warn(sprintf "attempting to set %s:%s:%s to %s - invalid value", $namespace, $clientid, $pref, defined $new ? $new : 'undef');
+
+		return wantarray ? ($old, 0) : $old;
+	}
+}
+
+sub _obj {}
+
+=head2 init( Hash )
+
+Initialises any preference values which currently do not exist.
+
+Hash is of the format: { 'prefname' => 'initial value' }
+
+=cut
+
+sub init {
+	my $class = shift;
+	my $hash  = shift;
+
+	for my $pref (keys %$hash) {
+
+		if (!exists $class->{'prefs'}->{ $pref }) {
+
+			my $value = ref $hash->{ $pref } eq 'CODE' ? $hash->{ $pref }->() : $hash->{ $pref };
+
+			$log->info("init " . $class->_root->{'namespace'} . ":" . ($class->{'clientid'} || '') . ":" . $pref .
+					   " to " . defined $value ? $value : 'undef');
+
+			$class->{'prefs'}->{ $pref } = $value;
+		}
+	}
+
+	$class->_root->save;
+}
+
+=head2 remove ( list )
+
+Removes (deletes) all preferences in the list.
+
+=cut
+
+sub remove {
+	my $class = shift;
+
+	while (my $pref  = shift) {
+
+		$log->info("removing " . $class->_root->{'namespace'} . ":" . ($class->{'clientid'} || '') . ":" . $pref);
+
+		delete ($class->{'prefs'}->{ $pref });
+	}
+
+	$class->_root->save;
+}
+
+=head2 all ( )
+
+Returns all preferences at this level (all global prefernces in a namespace, or all client preferences in a namespace).
+
+=cut
+
+sub all {
+	my $class = shift;
+
+	my %prefs = %{$class->{'prefs'}};
+
+	for my $pref (keys %prefs) {
+		delete $prefs{$pref} if $pref =~ /^\_/;
+	}
+
+	return \%prefs;
+}
+
+sub AUTOLOAD {
+	my $class = shift;
+
+	my $package = blessed($class);
+
+	our $AUTOLOAD;
+
+	my ($pref) = $AUTOLOAD =~ /$package\:\:(.*)/;
+
+	return if (!$pref || $pref eq 'DESTROY');
+
+	if ($optimiseAccessors) {
+
+		$log->debug("creating accessor for " . $class->_root->{'namespace'} . ":" . ($class->{'clientid'} || '') . ":" . $pref);
+
+		no strict 'refs';
+		*{ $AUTOLOAD } = sub { @_ == 1 ? shift->{'prefs'}->{ $pref } : shift->set($pref, shift) };
+	}
+
+	return @_ == 0 ? $class->{'prefs'}->{ $pref } : $class->set($pref, shift);
+}
+
+=head2 SEE ALSO
+
+L<Slim::Utils::Prefs::Base>
+L<Slim::Utils::Prefs::Namespace>
+L<Slim::Utils::Prefs::Client>
+L<Slim::Utils::Preds::OldPrefs>
+
+=cut
+
+1;

Propchange: trunk/server/Slim/Utils/Prefs/Base.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/server/Slim/Utils/Prefs/Base.pm
------------------------------------------------------------------------------
    svn:keywords = Id Author LastChangedDate LastChangedBy

Propchange: trunk/server/Slim/Utils/Prefs/Base.pm
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: trunk/server/Slim/Utils/Prefs/Client.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Utils/Prefs/Client.pm?rev=11744&view=auto
==============================================================================
--- trunk/server/Slim/Utils/Prefs/Client.pm (added)
+++ trunk/server/Slim/Utils/Prefs/Client.pm Wed Apr 11 07:56:30 2007
@@ -1,0 +1,78 @@
+package Slim::Utils::Prefs::Client;
+
+# $Id$
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License,
+# version 2.
+
+=head1 NAME
+
+Slim::Utils::Prefs::Client
+
+=head1 DESCRIPTION
+
+Class for implementing object to hold per client preferences within a namespace.
+
+=head1 METHODS
+
+=cut
+
+use strict;
+
+use base qw(Slim::Utils::Prefs::Base);
+
+use Slim::Utils::Log;
+
+my $log = logger('prefs');
+
+sub new {
+	my $ref    = shift;
+	my $parent = shift;
+	my $client = shift;
+
+	my $clientid = $client->id;
+
+	my $class = bless {
+		'clientid'  => $clientid,
+		'parent'    => $parent,
+	}, $ref;
+
+	$class->{'prefs'} = $parent->{'prefs'}->{"_client:$clientid"} ||= {
+		'_version' => 0,
+	};
+
+	for my $version (sort keys %{$parent->{'migratecb'}}) {
+
+		if ($class->{'prefs'}->{'_version'} < $version) {
+
+			if ($parent->{'migratecb'}->{ $version }->($class, $client)) {
+
+				$log->info("migrating client prefs $parent->{'namespace'} to version $version");
+
+				$class->{'prefs'}->{'_version'} = $version;
+
+			} else {
+
+				$log->warn("failed to migrate client prefs for $class->{'namespace'} to version $version");
+			}
+		}
+	}
+
+	return $class;
+}
+
+sub _root { shift->{'parent'} }
+
+sub _obj { Slim::Player::Client::getClient(shift->{'clientid'}) }
+
+=head2 SEE ALSO
+
+L<Slim::Utils::Prefs::Base>
+L<Slim::Utils::Prefs::Namespace>
+L<Slim::Utils::Prefs::Client>
+L<Slim::Utils::Preds::OldPrefs>
+
+=cut
+
+1;

Propchange: trunk/server/Slim/Utils/Prefs/Client.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/server/Slim/Utils/Prefs/Client.pm
------------------------------------------------------------------------------
    svn:keywords = Id Author LastChangedDate LastChangedBy

Propchange: trunk/server/Slim/Utils/Prefs/Client.pm
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: trunk/server/Slim/Utils/Prefs/Namespace.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Utils/Prefs/Namespace.pm?rev=11744&view=auto
==============================================================================
--- trunk/server/Slim/Utils/Prefs/Namespace.pm (added)
+++ trunk/server/Slim/Utils/Prefs/Namespace.pm Wed Apr 11 07:56:30 2007
@@ -1,0 +1,274 @@
+package Slim::Utils::Prefs::Namespace;
+
+# $Id$
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License, 
+# version 2.
+
+=head1 NAME
+
+Slim::Utils::Prefs::Namespace
+
+=head1 DESCRIPTION
+
+Class for implementing object to hold per namespace global perferences
+
+=head1 METHODS
+
+=cut
+
+use strict;
+
+use base qw(Slim::Utils::Prefs::Base);
+
+use File::Spec::Functions qw(:ALL);
+use YAML::Syck;
+use File::Slurp;
+
+use Slim::Utils::Prefs::Client;
+use Slim::Utils::Log;
+
+my $log = logger('prefs');
+
+# Simple validator functions which may be references by name in setValidate calls
+my $simpleValidators = {
+	#                   $_[0] = pref, $_[1] = value, $_[2] = params hash, $_[3] = old value, $_[4] = object (client) if appropriate
+	'int'      => sub { $_[1] =~ /^-?\d+$/ },
+	'num'      => sub { $_[1] =~ /^-?\.?\d+\.?\d*$/ },
+	'intlimit' => sub { $_[1] =~ /^-?\d+$/ && $_[1] >= $_[2]->{'low'} && $_[1] <= $_[2]->{'high'} },
+	'numlimit' => sub { $_[1] =~ /^-?\.?\d+\.?\d*$/ && $_[1] >= $_[2]->{'low'} && $_[1] <= $_[2]->{'high'} },
+	'array'    => sub { ref $_[1] eq 'ARRAY' },
+	'hash'     => sub { ref $_[1] eq 'HASH' },
+	'defined'  => sub { defined $_[1] },
+	'false'    => sub { 0 },
+};
+
+sub new {
+	my $ref       = shift;
+	my $namespace = shift;
+	my $path      = shift;
+
+	my $class = bless {
+		'namespace' => $namespace,
+		'file'      => catdir($path, "$namespace.prefs"),
+		'clients'   => {},
+		'validators'=> {},
+		'validparam'=> {},
+		'onchange'  => {},
+		'migratecb' => {},
+	}, $ref;
+
+	$class->{'prefs'} = $class->_load || {
+		'_version'   => 0,
+	};
+
+	return $class;
+}
+
+sub _root { shift }
+
+=head2 setValidate( $args, list )
+
+Associates a validator function with the preferences listed by list.
+
+$args may either be one of the following: 'int', 'num', 'array', 'hash', 'defined', 'false'
+
+or a hash containing the key 'validator' which specifies either 'intlimit' or 'numlimit' of a callback function.
+
+In the case of a hash the hash is stored and passed to the validator function to provide parameters to the validation function.
+The built in 'intlimit' and 'num' limit require 'low' and 'high' parameters:
+
+e.g. $prefs->setValidate({ 'validator' => 'intlimit', 'low' => 1 'high' => 10 }, 'pref1');
+
+This ensures pref1 is only set to integer values between 1 and 10 (inclusive).
+
+If callback function is specified for the validator it will be called with the following parameters:
+
+$prefname, potential new value, params hash (as stored with setValidate), old value, undef or $client
+
+=cut
+
+sub setValidate {
+	my $class  = shift;
+	my $args   = shift;
+
+	my ($validator, $params) = ref $args eq 'HASH' ? ($args->{'validator'}, $args) : ($args, undef);
+
+	$validator = $simpleValidators->{ $validator } || $validator;
+
+	unless (ref $validator eq 'CODE') {
+		logError("invalid validator callback - not registering");
+		return;
+	}
+
+	while (my $pref = shift) {
+
+		$log->debug(sprintf "registering %s for $class->{'namespace'}:$pref", Slim::Utils::PerlRunTime::realNameForCodeRef($validator));
+
+		$class->{'validators'}->{ $pref }  = $validator;
+		$class->{'validparams'}->{ $pref } = $params if $params;
+	}
+}
+
+=head2 setchange( $callback, list )
+
+Associates callback function $callback with the preferences listed by list.
+
+Callback functions will be called with the following parameters:
+
+prefname, new value, undef or $client
+
+=cut
+
+sub setChange {
+	my $class  = shift;
+	my $change = shift;
+
+	while (my $pref = shift) {
+
+		$log->debug(sprintf "registering %s for $class->{'namespace'}:$pref", Slim::Utils::PerlRunTime::realNameForCodeRef($change));
+
+		$class->{'onchange'}->{ $pref } = $change;
+	}
+}
+
+=head2 client( $client )
+
+Returns a preference client object for client $client.  This is used to access client preferences for a namespace:
+
+$prefs->client($client)->get('pref1');
+
+=cut
+
+sub client {
+	my $class  = shift;
+	my $client = shift;
+
+	return $class->{'clients'}->{ $client->id } ||= Slim::Utils::Prefs::Client->new($class, $client);
+}
+
+sub _load {
+	my $class = shift;
+
+	my $prefs;
+
+	if (-r $class->{'file'}) {
+
+		$prefs = eval { LoadFile($class->{'file'}) };
+
+		if ($@) {
+			$log->info("can't read $class->{'file'} : $@");
+		}
+	}
+
+	return $prefs;
+}
+
+=head2 save( )
+
+Trigger saving of this namespace's preferences.  This is delayed by 10 seconds to batch up changes.
+
+=cut
+
+sub save {
+	my $class = shift;
+
+	return if ($class->{'writepending'});
+
+	Slim::Utils::Timers::setTimer($class, time() + 10, \&savenow);
+
+	$class->{'writepending'} = 1;
+}
+
+=head2 savenow( )
+
+Save this namespace's preferences immediately.
+
+=cut
+
+sub savenow {
+	my $class = shift;
+
+	return unless ($class->{'writepending'});
+
+	$log->info("saving prefs for $class->{'namespace'} to $class->{'file'}");
+
+	eval { File::Slurp::write_file($class->{'file'}, { 'atomic' => 1 }, Dump($class->{'prefs'}) ) };
+
+	if ($@) {
+		logError("can't save $class->{'file'}: $@");
+	}
+
+	$class->{'writepending'} = 0;
+
+	Slim::Utils::Timers::killTimers($class, \&savenow);
+}
+
+=head2 migrate( $version, $callback )
+
+Potentially migrate this namespace to version $version.  If the current version number for this namespace is < $version then $callback
+is executed.  If $callback returns true then the namespace version is set to $version.
+
+The callback is executed with the namespace class as its only parameter.
+
+=cut
+
+sub migrate {
+	my $class    = shift;
+	my $version  = shift;
+	my $callback = shift;
+
+	if ($version > $class->{'prefs'}->{'_version'} && ref $callback eq 'CODE') {
+
+		if ($callback->($class)) {
+
+			$log->info("migrated prefs for $class->{'namespace'} to version $version");
+
+			$class->{'prefs'}->{'_version'} = $version;
+
+		} else {
+
+			$log->warn("failed to migrate prefs for $class->{'namespace'} to version $version");
+		}
+
+		$class->save;
+	}
+}
+
+=head2 migrateClient( $version, $callback )
+
+Potentially migrate client preferences for this namespace to version $version.
+
+If the current version number for new client for this namespace is < $version then $callback
+is executed.  If $callback returns true then the client namespace version is set to $version.
+
+The callback is excuted with the following parameters:
+
+client preference class, $client object
+
+NB dormant clients may not attach to the server for a while.  This mechanism allows multiple migrate
+functions to be performed in order for such clients to bring them up to the latest version.
+
+=cut
+
+sub migrateClient {
+	my $class    = shift;
+	my $version  = shift;
+	my $callback = shift;
+
+	$log->info("registering client migrate function for $class->{'namespace'} to version $version");
+
+	$class->{'migratecb'}->{ $version } = $callback;
+}
+
+=head2 SEE ALSO
+
+L<Slim::Utils::Prefs::Base>
+L<Slim::Utils::Prefs::Namespace>
+L<Slim::Utils::Prefs::Client>
+L<Slim::Utils::Preds::OldPrefs>
+
+=cut
+
+1;

Propchange: trunk/server/Slim/Utils/Prefs/Namespace.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/server/Slim/Utils/Prefs/Namespace.pm
------------------------------------------------------------------------------
    svn:keywords = Id Author LastChangedDate LastChangedBy

Propchange: trunk/server/Slim/Utils/Prefs/Namespace.pm
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: trunk/server/Slim/Utils/Prefs/OldPrefs.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Utils/Prefs/OldPrefs.pm?rev=11744&view=auto
==============================================================================
--- trunk/server/Slim/Utils/Prefs/OldPrefs.pm (added)
+++ trunk/server/Slim/Utils/Prefs/OldPrefs.pm Wed Apr 11 07:56:30 2007
@@ -1,0 +1,87 @@
+package Slim::Utils::Prefs::OldPrefs;
+
+=head1 NAME
+
+Slim::Utils::Prefs::OldPrefs
+
+=head1 DESCRIPTION
+
+Class to allow loading of the old 6.0/6.1/6.2/6.3/6.5 YAML based server preferences so they can be migrated to new preferences.
+
+=head1 METHODS
+
+=cut
+
+use strict;
+
+use YAML::Syck;
+use FindBin qw($Bin);
+use File::Spec::Functions qw(:ALL);
+
+my $oldprefs;
+
+=head2 get( $prefname )
+
+Returns the value for old preference $prefname.
+
+=cut
+
+sub get {
+	my $class = shift;
+	my $pref  = shift;
+
+	$oldprefs ||= LoadFile(_oldPath());
+
+	$oldprefs->{ $pref };
+}
+
+=head2 clientGet( $client, $prefname )
+
+Returns the value for old client preference $prefname.
+
+=cut
+
+sub clientGet {
+	my $class = shift;
+	my $client = shift;
+	my $pref  = shift;
+
+	$oldprefs ||= LoadFile(_oldPath());
+
+	$oldprefs->{'clients'}->{ $client->id }->{ $pref } if $oldprefs->{'clients'}->{ $client->id };
+}
+
+sub _oldPath {
+
+	if (Slim::Utils::OSDetect::OS() eq 'mac') {
+
+		return catdir($ENV{'HOME'}, 'Library', 'SlimDevices', 'slimserver.pref');
+
+	} elsif (Slim::Utils::OSDetect::OS() eq 'win')  {
+
+		return catdir($Bin, 'slimserver.pref');
+
+	} elsif (-r '/etc/slimserver.conf') {
+
+		return '/etc/slimserver.conf';
+
+	} elsif (-r catdir(Slim::Utils::OSDetect::dirsFor('prefs'), 'slimserver.pref')) {
+
+		return catdir(Slim::Utils::OSDetect::dirsFor('prefs'), 'slimserver.pref');
+
+	} else {
+
+	 	return catdir($ENV{'HOME'}, 'slimserver.pref');
+	}
+}
+
+=head2 SEE ALSO
+
+L<Slim::Utils::Prefs::Base>
+L<Slim::Utils::Prefs::Namespace>
+L<Slim::Utils::Prefs::Client>
+L<Slim::Utils::Preds::OldPrefs>
+
+=cut
+
+1;

Propchange: trunk/server/Slim/Utils/Prefs/OldPrefs.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/server/Slim/Utils/Prefs/OldPrefs.pm
------------------------------------------------------------------------------
    svn:keywords = Id Author LastChangedDate LastChangedBy

Propchange: trunk/server/Slim/Utils/Prefs/OldPrefs.pm
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: trunk/server/Slim/Web/Settings.pm
URL: http://svn.slimdevices.com/trunk/server/Slim/Web/Settings.pm?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/Slim/Web/Settings.pm (original)
+++ trunk/server/Slim/Web/Settings.pm Wed Apr 11 07:56:30 2007
@@ -14,6 +14,8 @@
 use Slim::Utils::Log;
 use Slim::Web::HTTP;
 use Slim::Web::Pages;
+
+use Scalar::Util qw(blessed);
 
 sub new {
 	my $class = shift;
@@ -62,14 +64,34 @@
 	# programatic validation via the prefs rework.
 	my @prefs = $class->prefs;
 
+	my $prefsClass = shift @prefs if (@prefs && blessed($prefs[0]));
+
 	for my $pref (@prefs) {
 
 		if ($paramRef->{'saveSettings'}) {
 
-			Slim::Utils::Prefs::set($pref, $paramRef->{$pref});
+			if ($prefsClass) {
+
+				my (undef, $ok) = $prefsClass->set($pref, $paramRef->{$pref});
+
+				if (!$ok) {
+					$paramRef->{'warning'} .= sprintf(Slim::Utils::Strings::string('SETTINGS_INVALIDVALUE'), $paramRef->{$pref}, $pref);
+				}
+
+			} else {
+
+				Slim::Utils::Prefs::set($pref, $paramRef->{$pref});
+			}
 		}
 
-		$paramRef->{'prefs'}->{$pref} = Slim::Utils::Prefs::get($pref);
+		if ($prefsClass) {
+
+			$paramRef->{'prefs'}->{$pref} = $prefsClass->get($pref);
+
+		} else {
+
+			$paramRef->{'prefs'}->{$pref} = Slim::Utils::Prefs::get($pref);
+		}
 	}
 
 	# Common values

Modified: trunk/server/slimserver.pl
URL: http://svn.slimdevices.com/trunk/server/slimserver.pl?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/slimserver.pl (original)
+++ trunk/server/slimserver.pl Wed Apr 11 07:56:30 2007
@@ -234,11 +234,7 @@
 	msg("SlimServer OSDetect init...\n");
 	Slim::Utils::OSDetect::init();
 
-	# initialize slimserver subsystems
-	msg("SlimServer settings init...\n");
-	initSettings();
-
-	# Now that the user might have changed - open the log files.
+	# open the log files
 	Slim::Utils::Log->init({
 		'logconf' => $logconf,
 		'logdir'  => $logdir,
@@ -247,11 +243,12 @@
 		'debug'   => $debug,
 	});
 
+	# initialize slimserver subsystems
+	msg("SlimServer settings init...\n");
+	initSettings();
+
 	# Redirect STDERR to the log file.
 	tie *STDERR, 'Slim::Utils::Log::Trapper';
-
-	# Load a log handler for prefs now.
-	Slim::Utils::Prefs::loadLogHandler();
 
 	my $log = logger('server');
 
@@ -872,6 +869,8 @@
 		Slim::Utils::Prefs::writePrefs();
 	}
 
+	Slim::Utils::Prefs::writeAll();
+
 	Slim::Networking::mDNS->stopAdvertising;
 
 	if (Slim::Utils::Prefs::get('persistPlaylists')) {

Modified: trunk/server/strings.txt
URL: http://svn.slimdevices.com/trunk/server/strings.txt?rev=11744&r1=11743&r2=11744&view=diff
==============================================================================
--- trunk/server/strings.txt (original)
+++ trunk/server/strings.txt Wed Apr 11 07:56:30 2007
@@ -12456,3 +12456,5 @@
 	DE	Schliessen
 	EN	Close
 
+SETTINGS_INVALIDVALUE
+	EN	Invalid value "%s" for %s



More information about the checkins mailing list