Index: Slim/Player/Sync.pm
===================================================================
--- Slim/Player/Sync.pm	(revision 22172)
+++ Slim/Player/Sync.pm	(working copy)
@@ -236,6 +236,12 @@
 		deleteSyncPrefs($lastInGroup, 1) if $lastInGroup;
 	}
 
+	# Clear current alarm if it was inherited from the sync group 
+	if ($client->alarmData->{currentAlarm} && $client->alarmData->{currentAlarm}->client ne $client) {
+		warn 'removing current alarm for ' . $client->name;
+		$client->alarmData->{currentAlarm} = undef;
+	}
+
 	if (Slim::Player::Source::playmode($client) ne 'stop') {
 		Slim::Player::Source::playmode($client, 'stop');
 		Slim::Control::Request::notifyFromArray($client, ['stop']);
@@ -277,6 +283,10 @@
 	$client->master($buddy);
 	
 	push (@{$client->master->slaves}, $client);
+
+	# Copy any current alarm from the buddy to the client
+	warn 'Adding current alarm for ' . $client->name;
+	$client->alarmData->{currentAlarm} = $buddy->alarmData->{currentAlarm};
 	
 	if (Slim::Player::Source::playmode($buddy) eq "play") {
 		$buddy->execute(["stop"]);
Index: Slim/Utils/Alarm.pm
===================================================================
--- Slim/Utils/Alarm.pm	(revision 22172)
+++ Slim/Utils/Alarm.pm	(working copy)
@@ -80,6 +80,8 @@
 	},
 );
 
+# Global count of the number of active alarms on the server
+my $activeAlarms = 0;
 
 ################################################################################
 =head1 INSTANCE METHODS
@@ -475,15 +477,24 @@
 		# Sound an Alarm (HWV 63)
 		$log->debug('Sounding alarm');
 
-		# Stop any other current alarm
-		if ($client->alarmData->{currentAlarm}) {
-			$log->debug('Stopping other current alarm');
-			$client->alarmData->{currentAlarm}->stop;
+		$activeAlarms++;
+
+		my @syncGroup = Slim::Player::Sync::syncedWith($client);
+		push @syncGroup, $client;
+
+		# Stop any other current alarm, including alarms on synced players and set current alarm to be this one
+		foreach my $buddy (@syncGroup) { 
+			warn $buddy->name . "\n";
+			if ($buddy->alarmData->{currentAlarm}) {
+				$log->debug('Stopping other current alarm on ' . $buddy->name);
+				$buddy->alarmData->{currentAlarm}->stop;
+			}
+
+			$buddy->alarmData->{lastAlarmTime} = $self->{_nextDue};
+			$buddy->alarmData->{currentAlarm} = $self;
 		}
 
-		$client->alarmData->{lastAlarmTime} = $self->{_nextDue};
 		$self->{_active} = 1;
-		$client->alarmData->{currentAlarm} = $self;
 
 		my $now = Time::HiRes::time(); 
 		# Bug 7818, count this as user interaction, even though it isn't really
@@ -497,11 +508,13 @@
 		$request = $client->execute(['power', 1]);
 		$request->source('ALARM');
 
-		$class->pushAlarmScreensaver($client);
+		foreach my $buddy (@syncGroup) {
+			$class->pushAlarmScreensaver($buddy);
 
-		# Set analogOutMode to subwoofer to force output through main speakers even if headphones are plugged in
-		# This needs doing a lot more thoroughly.  Bug 8146 
-		$client->can('setAnalogOutMode') && $client->setAnalogOutMode(1);
+			# Set analogOutMode to subwoofer to force output through main speakers even if headphones are plugged in
+			# This needs doing a lot more thoroughly.  Bug 8146 
+			$buddy->can('setAnalogOutMode') && $buddy->setAnalogOutMode(1);
+		}
 
 		# Set up volume
 		my $currentVolume = $client->volume;
@@ -543,12 +556,6 @@
 
 		# Allow a slight delay for things to load up then tell the user what's going on
 		Slim::Utils::Timers::setTimer($client, Time::HiRes::time() + 2, sub {
-			# Show a long-lasting notification unless we've already pushed into an alarm screensaver
-			my $showBrieflyDur = 30;
-			if (Slim::Buttons::Common::mode($client) eq $class->alarmScreensaver) {
-				$showBrieflyDur = $SHOW_BRIEFLY_DUR;
-			}
-
 			my $line1 = $client->string('ALARM_NOW_PLAYING');
 
 			my $line2; 
@@ -571,10 +578,19 @@
 				$line2 = $client->string('CURRENT_PLAYLIST');
 			}
 
-			$client->showBriefly({
-				line => [ $line1, $line2 ],
-				duration => $showBrieflyDur,
-			});
+			foreach my $buddy (@syncGroup) {
+				# Show a long-lasting notification unless we've already pushed into an alarm screensaver
+				my $showBrieflyDur = 30;
+				if (Slim::Buttons::Common::mode($buddy) eq $class->alarmScreensaver) {
+					$showBrieflyDur = $SHOW_BRIEFLY_DUR;
+				}
+
+				$buddy->showBriefly({
+					line => [ $line1, $line2 ],
+					duration => $showBrieflyDur,
+					block => 1,
+				});
+			}
 		} );
 
 		# Set up subscription to end the alarm on user activity
@@ -612,6 +628,9 @@
 	return unless $self->{_active};
 
 	my $client = $self->client;
+	my @syncGroup = Slim::Player::Sync::syncedWith($client);
+	push @syncGroup, $client;
+
 	my $class = ref $self;
 
 	# don't snooze again if we're already snoozing.
@@ -650,10 +669,12 @@
 		# Set up snooze subscription to end snooze on user activity
 		$class->_setAlarmSubscription($client, 1);
 
-		$client->showBriefly({
-			line => [$client->string('ALARM_SNOOZE')],
-			duration => $SHOW_BRIEFLY_DUR,
-		});
+		foreach my $buddy (@syncGroup) {
+			$buddy->showBriefly({
+				line => [$buddy->string('ALARM_SNOOZE')],
+				duration => $SHOW_BRIEFLY_DUR,
+			});
+		}
 	}
 
 	$class->pushAlarmScreensaver($client);
@@ -680,6 +701,8 @@
 
 	my $class = ref $self;
 	my $client = $self->client;
+	my @syncGroup = Slim::Player::Sync::syncedWith($client);
+	push @syncGroup, $client;
 
 	$self->{_snoozeActive} = 0;
 	
@@ -689,10 +712,12 @@
 		$request->source('ALARM');
 	}
 
-	$client->showBriefly({
-		line     => [$client->string('ALARM_SNOOZE_ENDED')],
-		duration => $SHOW_BRIEFLY_DUR,
-	});
+	foreach my $buddy (@syncGroup) {
+		$buddy->showBriefly({
+			line     => [$buddy->string('ALARM_SNOOZE_ENDED')],
+			duration => $SHOW_BRIEFLY_DUR,
+		});
+	}
 	
 	# Reset the subscription to end the alarm on user activity
 	$class->_setAlarmSubscription($client);
@@ -714,17 +739,27 @@
 	my $self = shift;
 
 	my $client = $self->client;
+	my @syncGroup = Slim::Player::Sync::syncedWith($client);
+	push @syncGroup, $client;
 
 	return unless $self->{_active};
 
-	if (defined $client->alarmData->{currentAlarm} && $client->alarmData->{currentAlarm} == $self) {
-		$client->alarmData->{currentAlarm} = undef;
+	$activeAlarms --;
+
+	foreach my $buddy (@syncGroup) {
+		if (defined $buddy->alarmData->{currentAlarm} && $buddy->alarmData->{currentAlarm} == $self) {
+			$buddy->alarmData->{currentAlarm} = undef;
+		}
 	}
+
 	$self->{_active} = 0;
 	$self->{_snoozeActive} = 0;
 
-	# Kill the subscription to automatically end this alarm on user activity
-	Slim::Control::Request::unsubscribe(\&_alarmEnd, $client);
+	# If this is the last active alarm, kill the subscription to end alarms on user activity
+	if (! $activeAlarms) {
+		$log->debug('Removing _alarmEnd subscription');
+		Slim::Control::Request::unsubscribe(\&_alarmEnd);
+	}
 
 	# Kill the callback to check for playback
 	Slim::Utils::Timers::killTimers($self, \&_checkPlaying);
@@ -735,17 +770,20 @@
 		$self->{_timeoutTimer} = undef;
 	}
 
-	# Restore analogOutMode to previous setting
-	$client->can('setAnalogOutMode') && $client->setAnalogOutMode();
+	my $class = ref $self;
 
-	my $class = ref $self;
 	$class->popAlarmScreensaver($client);
 
-	$client->showBriefly({
-		line => [$client->string('ALARM_STOPPED')],
-		duration => $SHOW_BRIEFLY_DUR,
-	});
+	foreach my $buddy (@syncGroup) {
+		# Restore analogOutMode to previous setting
+		$buddy->can('setAnalogOutMode') && $buddy->setAnalogOutMode();
 
+		$buddy->showBriefly({
+			line => [$buddy->string('ALARM_STOPPED')],
+			duration => $SHOW_BRIEFLY_DUR,
+		});
+	}
+
 	# Send notifications
 	Slim::Control::Request::notifyFromArray($client, ['alarm', 'end', $self->{_id}]);
 }
@@ -987,30 +1025,28 @@
 	my $snooze = shift;
 
 	# Remove any subscription for this client
-	Slim::Control::Request::unsubscribe(\&_alarmEnd, $client);
+	Slim::Control::Request::unsubscribe(\&_alarmEnd);
 
 	my $currentAlarm = $client->alarmData->{currentAlarm};
 
 	return unless defined $currentAlarm;
 
-	$log->debug('Adding ' . ($snooze ? 'snooze' : 'alarm') . ' subscription');
+	$log->debug('Adding subscription');
 
-	my $stopCommands;
+	# A snooze should be cancelled on anything the user does that results in music playing and also on any
+	# "off" action:
+	# power needs to be caught on its own as the music is paused
+	# pause/play when paused results in pause
+	# fwd/rew and (hopefully) commands that load a new playlist result in 'playlist jump'
 
-	if ($snooze) {
-		# The snooze should be cancelled on anything the user does that results in music playing and also on any
-		# "off" action:
-		# power needs to be caught on its own as the music is paused
-		# pause/play when paused results in pause
-		# fwd/rew and (hopefully) commands that load a new playlist result in 'playlist jump'
-		$stopCommands = ['power', 'pause', 'stop', 'playlist'];
-	} else {
-		# The alarm should be cancelled on anything the user does that would stop the music
-		# power needs to be caught on its own as the music could potentially be stopped if the alarm playlist failed
-		# for some reason
-		$stopCommands =  ['pause', 'stop', 'power'];
-	}
-	Slim::Control::Request::subscribe(\&_alarmEnd, [$stopCommands], $client);
+	# An alarm should be cancelled on anything the user does that would stop the music
+	# power needs to be caught on its own as the music could potentially be stopped if the alarm playlist failed
+	# for some reason
+	my $stopCommands = ['power', 'pause', 'stop', 'playlist'];
+
+	# There may already be an active subscription if another alarm is active, this won't matter however - only one
+	# will exist at once and any subscription will service all alarms.
+	Slim::Control::Request::subscribe(\&_alarmEnd, [$stopCommands]);
 }
 
 =head2 getCurrentAlarm( $client )
@@ -1507,9 +1543,10 @@
 
 	my $client = $request->client;
 
-	$log->debug(sub {'_alarmEnd called with request: ' . $request->getRequestString});
+	$log->debug(sub {'_alarmEnd called with request: ' . $request->getRequestString . ' from client ' . $client->name});
 
 	my $currentAlarm = $client->alarmData->{currentAlarm};
+		
 	if (! defined $currentAlarm) {
 		$log->debug('No current alarm.  Doing nothing.');
 		return;
@@ -1523,6 +1560,7 @@
 	}
 
 	# power always ends the alarm, whether snoozing or not
+	# We only stop on playlist jump for snoozes
 	if ($currentAlarm->{_snoozeActive} && $request->getRequest(0) ne 'power') {
 		# When snoozing we should end on 'playlist jump' but can only filter on playlist
 		if ($request->getRequest(0) eq 'playlist' && $request->getRequest(1) ne 'jump') {
@@ -1534,9 +1572,13 @@
 		$log->debug('Stopping snooze');
 		Slim::Utils::Timers::killTimers($currentAlarm, \&stopSnooze);
 		$currentAlarm->stopSnooze(0);
-	} else {
-		$log->debug('Stopping alarm');
-		$currentAlarm->stop;
+	} elsif ($request->getRequest(0) ne 'playlist') {
+		# Only stop for power if the request turned the client off - otherwise alarms could stop when synced
+		# players are turned on.
+		if ($request->getRequest(0) ne 'power' || ! $client->power) {
+			$log->debug('Stopping alarm');
+			$currentAlarm->stop;
+		}
 	}
 }