From 467365730c5e976808ff3f42fd8e5de08bed0cce Mon Sep 17 00:00:00 2001
From: Junior <juniorcesar.utfpr@gmail.com>
Date: Tue, 24 Sep 2013 17:40:58 -0300
Subject: [PATCH] Adding silent mode to start the slideshow

---
 android/sdremote/res/values/strings.xml            |    2 +
 android/sdremote/res/xml/preferences.xml           |    7 +-
 .../impressremote/activity/ComputersActivity.java  |   74 +-
 .../impressremote/activity/SlideShowActivity.java  | 1008 ++++++++++----------
 .../impressremote/util/Preferences.java            |   39 +-
 5 files changed, 547 insertions(+), 583 deletions(-)

diff --git a/android/sdremote/res/values/strings.xml b/android/sdremote/res/values/strings.xml
index 0eefa95..8f8b285 100644
--- a/android/sdremote/res/values/strings.xml
+++ b/android/sdremote/res/values/strings.xml
@@ -64,6 +64,8 @@
     <string name="preferences_volume_keys_actions_summary">Switch slides and activate animations using volume keys</string>
     <string name="preferences_keep_screen_on_title">Screen on</string>
     <string name="preferences_keep_screen_on_summary">Keep screen on while presenting</string>
+    <string name="preferences_keep_silent_mode_on_title">Silent mode on</string>
+    <string name="preferences_keep_silent_mode_on_summary">Keep silent mode on while presenting</string>
 
     <string name="requirements_libreoffice_version">LibreOffice version 4.0.3 or higher running on a computer.</string>
     <string name="requirements_libreoffice_general_enabled">Impress Remote enabled at “Tools → Options → LibreOffice Impress → General” in LibreOffice Impress.</string>
diff --git a/android/sdremote/res/xml/preferences.xml b/android/sdremote/res/xml/preferences.xml
index 104c528..b4e9122 100644
--- a/android/sdremote/res/xml/preferences.xml
+++ b/android/sdremote/res/xml/preferences.xml
@@ -3,14 +3,17 @@
 
     <CheckBoxPreference
         android:key="volume_keys_actions"
-        android:defaultValue="true"
         android:title="@string/preferences_volume_keys_actions_title"
         android:summary="@string/preferences_volume_keys_actions_summary"/>
 
     <CheckBoxPreference
         android:key="keep_screen_on"
-        android:defaultValue="true"
         android:title="@string/preferences_keep_screen_on_title"
         android:summary="@string/preferences_keep_screen_on_summary"/>
+    
+    <CheckBoxPreference 
+        android:key="keep_silent_mode_on"
+        android:summary="@string/preferences_keep_silent_mode_on_summary"
+        android:title="@string/preferences_keep_silent_mode_on_title"/>
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java b/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
index 7ccd18e..aaecd83 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/activity/ComputersActivity.java
@@ -19,14 +19,14 @@ import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuItem;
+
 import org.libreoffice.impressremote.adapter.ComputersPagerAdapter;
 import org.libreoffice.impressremote.fragment.ComputersFragment;
 import org.libreoffice.impressremote.util.BluetoothOperator;
-import org.libreoffice.impressremote.util.Fragments;
+import org.libreoffice.impressremote.util.FragmentOperator;
 import org.libreoffice.impressremote.util.Intents;
 import org.libreoffice.impressremote.R;
 import org.libreoffice.impressremote.util.Preferences;
-import org.libreoffice.impressremote.util.SavedStates;
 
 public class ComputersActivity extends SherlockFragmentActivity implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
     private static final class TabsIndices {
@@ -36,45 +36,16 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
         public static final int BLUETOOTH = 0;
         public static final int WIFI = 1;
     }
-
-    private boolean mBluetoothWasEnabled;
-
+    
+	
     @Override
     protected void onCreate(Bundle aSavedInstanceState) {
         super.onCreate(aSavedInstanceState);
 
-        saveBluetoothState(aSavedInstanceState);
-        enableBluetooth();
-
         setUpTitle();
         setUpContent();
     }
 
-    private void saveBluetoothState(Bundle aSavedInstanceState) {
-        // In more ideal world this work should be done at the service.
-        // Unfortunately service cannot save or restore its state
-        // but enabling or disabling Bluetooth is quite a long operation,
-        // so we have more chances to manage state right at the activity.
-
-        if (!BluetoothOperator.isAvailable()) {
-            return;
-        }
-
-        mBluetoothWasEnabled = wasBluetoothEnabled(aSavedInstanceState);
-    }
-
-    private boolean wasBluetoothEnabled(Bundle aSavedInstanceState) {
-        if (aSavedInstanceState == null) {
-            return BluetoothOperator.getAdapter().isEnabled();
-        }
-
-        return aSavedInstanceState.getBoolean(SavedStates.Keys.BLUETOOTH_ENABLED);
-    }
-
-    private void enableBluetooth() {
-        BluetoothOperator.enable();
-    }
-
     private void setUpTitle() {
         // Looks hacky but it seems to be the best way to set activity’s title
         // different to application’s label. The other way is setting title
@@ -184,7 +155,7 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
     private void setUpComputersList() {
         Fragment aComputersFragment = ComputersFragment.newInstance(ComputersFragment.Type.WIFI);
 
-        Fragments.Operator.add(this, aComputersFragment);
+        FragmentOperator.addFragment(this, aComputersFragment);
     }
 
     @Override
@@ -265,40 +236,7 @@ public class ComputersActivity extends SherlockFragmentActivity implements Actio
 
         aPreferences.setInt(Preferences.Keys.SELECTED_COMPUTERS_TAB_INDEX, aTabIndex);
     }
-
-    @Override
-    protected void onSaveInstanceState(Bundle aSavedInstanceState) {
-        super.onSaveInstanceState(aSavedInstanceState);
-
-        rememberBluetoothState(aSavedInstanceState);
-    }
-
-    private void rememberBluetoothState(Bundle aSavedInstanceState) {
-        aSavedInstanceState.putBoolean(SavedStates.Keys.BLUETOOTH_ENABLED, mBluetoothWasEnabled);
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-
-        restoreBluetoothState();
-    }
-
-    private void restoreBluetoothState() {
-        if (!BluetoothOperator.isAvailable()) {
-            return;
-        }
-
-        if (mBluetoothWasEnabled) {
-            return;
-        }
-
-        disableBluetooth();
-    }
-
-    private void disableBluetooth() {
-        BluetoothOperator.disable();
-    }
+    
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java b/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
index 3c41ecc..747d114 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/activity/SlideShowActivity.java
@@ -14,6 +14,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.media.AudioManager;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.support.v4.app.DialogFragment;
@@ -25,6 +26,7 @@ import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.app.SherlockFragmentActivity;
 import com.actionbarsherlock.view.Menu;
 import com.actionbarsherlock.view.MenuItem;
+
 import org.libreoffice.impressremote.R;
 import org.libreoffice.impressremote.communication.CommunicationService;
 import org.libreoffice.impressremote.communication.SlideShow;
@@ -34,506 +36,520 @@ import org.libreoffice.impressremote.fragment.SlidesGridFragment;
 import org.libreoffice.impressremote.fragment.SlidesPagerFragment;
 import org.libreoffice.impressremote.fragment.TimerEditingDialog;
 import org.libreoffice.impressremote.fragment.TimerSettingDialog;
-import org.libreoffice.impressremote.util.Fragments;
+import org.libreoffice.impressremote.util.FragmentOperator;
 import org.libreoffice.impressremote.util.Intents;
 import org.libreoffice.impressremote.util.Preferences;
 import org.libreoffice.impressremote.util.SavedStates;
 
-public class SlideShowActivity extends SherlockFragmentActivity implements ServiceConnection {
-    public static enum Mode {
-        PAGER, GRID, EMPTY
-    }
-
-    private Mode mMode;
-
-    private CommunicationService mCommunicationService;
-    private IntentsReceiver mIntentsReceiver;
-
-    @Override
-    protected void onCreate(Bundle aSavedInstanceState) {
-        super.onCreate(aSavedInstanceState);
-
-        mMode = loadMode(aSavedInstanceState);
-
-        setUpHomeButton();
-        setUpFragment();
-        setUpKeepingScreenOn();
-
-        bindService();
-    }
-
-    private Mode loadMode(Bundle aSavedInstanceState) {
-        if (aSavedInstanceState == null) {
-            return Mode.PAGER;
-        }
-
-        return (Mode) aSavedInstanceState.getSerializable(SavedStates.Keys.MODE);
-    }
-
-    private void setUpHomeButton() {
-        getSupportActionBar().setHomeButtonEnabled(true);
-    }
-
-    private void setUpFragment() {
-        Fragments.Operator.replaceAnimated(this, buildFragment());
-    }
-
-    private Fragment buildFragment() {
-        switch (mMode) {
-            case PAGER:
-                return SlidesPagerFragment.newInstance();
-
-            case GRID:
-                return SlidesGridFragment.newInstance();
-
-            case EMPTY:
-                return EmptySlideFragment.newInstance();
-
-            default:
-                return SlidesPagerFragment.newInstance();
-        }
-    }
-
-    private void setUpKeepingScreenOn() {
-        findViewById(android.R.id.content).setKeepScreenOn(isKeepingScreenOnRequired());
-    }
-
-    private boolean isKeepingScreenOnRequired() {
-        Preferences aPreferences = Preferences.getSettingsInstance(this);
-
-        return aPreferences.getBoolean(Preferences.Keys.KEEP_SCREEN_ON);
-    }
-
-    private void bindService() {
-        Intent aIntent = Intents.buildCommunicationServiceIntent(this);
-        bindService(aIntent, this, Context.BIND_AUTO_CREATE);
-    }
-
-    @Override
-    public void onServiceConnected(ComponentName mComponentName, IBinder aBinder) {
-        CommunicationService.ServiceBinder aServiceBinder = (CommunicationService.ServiceBinder) aBinder;
-        mCommunicationService = aServiceBinder.getService();
-
-        startSlideShow();
-        resumeTimer();
-    }
-
-    private void startSlideShow() {
-        if (mCommunicationService.getSlideShow().isRunning()) {
-            setUpSlideShowInformation();
-            return;
-        }
-
-        mCommunicationService.getCommandsTransmitter().startPresentation();
-    }
-
-    private void resumeTimer() {
-        if (!isServiceBound()) {
-            return;
-        }
-
-        mCommunicationService.getSlideShow().getTimer().resume();
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-
-        resumeTimer();
-
-        registerIntentsReceiver();
-    }
-
-    private void registerIntentsReceiver() {
-        mIntentsReceiver = new IntentsReceiver(this);
-        IntentFilter aIntentFilter = buildIntentsReceiverFilter();
-
-        getBroadcastManager().registerReceiver(mIntentsReceiver, aIntentFilter);
-    }
-
-    private static final class IntentsReceiver extends BroadcastReceiver {
-        private final SlideShowActivity mSlideShowActivity;
-
-        private IntentsReceiver(SlideShowActivity aSlideShowActivity) {
-            mSlideShowActivity = aSlideShowActivity;
-        }
-
-        @Override
-        public void onReceive(Context aContext, Intent aIntent) {
-            if (Intents.Actions.SLIDE_SHOW_MODE_CHANGED.equals(aIntent.getAction())) {
-                Mode aMode = (Mode) aIntent.getSerializableExtra(Intents.Extras.MODE);
-                mSlideShowActivity.changeMode(aMode);
-                return;
-            }
-
-            if (Intents.Actions.SLIDE_CHANGED.equals(aIntent.getAction())) {
-                mSlideShowActivity.setUpSlideShowInformation();
-                return;
-            }
-
-            if (Intents.Actions.TIMER_UPDATED.equals(aIntent.getAction())) {
-                mSlideShowActivity.setUpSlideShowInformation();
-                return;
-            }
-
-            if (Intents.Actions.TIMER_STARTED.equals(aIntent.getAction())) {
-                int aMinutesLength = aIntent.getIntExtra(Intents.Extras.MINUTES, 0);
-                mSlideShowActivity.startTimer(aMinutesLength);
-                mSlideShowActivity.setUpSlideShowInformation();
-                return;
-            }
-
-            if (Intents.Actions.TIMER_RESUMED.equals(aIntent.getAction())) {
-                mSlideShowActivity.resumeTimer();
-                return;
-            }
-
-            if (Intents.Actions.TIMER_CHANGED.equals(aIntent.getAction())) {
-                int aMinutesLength = aIntent.getIntExtra(Intents.Extras.MINUTES, 0);
-                mSlideShowActivity.changeTimer(aMinutesLength);
-                mSlideShowActivity.resumeTimer();
-                mSlideShowActivity.setUpSlideShowInformation();
-            }
-        }
-    }
-
-    private IntentFilter buildIntentsReceiverFilter() {
-        IntentFilter aIntentFilter = new IntentFilter();
-        aIntentFilter.addAction(Intents.Actions.SLIDE_SHOW_MODE_CHANGED);
-        aIntentFilter.addAction(Intents.Actions.SLIDE_CHANGED);
-        aIntentFilter.addAction(Intents.Actions.TIMER_UPDATED);
-        aIntentFilter.addAction(Intents.Actions.TIMER_STARTED);
-        aIntentFilter.addAction(Intents.Actions.TIMER_RESUMED);
-        aIntentFilter.addAction(Intents.Actions.TIMER_CHANGED);
-
-        return aIntentFilter;
-    }
-
-    private LocalBroadcastManager getBroadcastManager() {
-        return LocalBroadcastManager.getInstance(getApplicationContext());
-    }
-
-    private void setUpSlideShowInformation() {
-        if (!isServiceBound()) {
-            return;
-        }
-
-        ActionBar aActionBar = getSupportActionBar();
-
-        aActionBar.setTitle(buildSlideShowProgress());
-        aActionBar.setSubtitle(buildSlideShowTimerProgress());
-    }
-
-    private boolean isServiceBound() {
-        return mCommunicationService != null;
-    }
-
-    private String buildSlideShowProgress() {
-        SlideShow aSlideShow = mCommunicationService.getSlideShow();
-
-        int aCurrentSlideIndex = aSlideShow.getHumanCurrentSlideIndex();
-        int aSlidesCount = aSlideShow.getSlidesCount();
-
-        return getString(R.string.mask_slide_show_progress, aCurrentSlideIndex, aSlidesCount);
-    }
-
-    private String buildSlideShowTimerProgress() {
-        Timer aTimer = mCommunicationService.getSlideShow().getTimer();
-
-        if (!aTimer.isSet()) {
-            return null;
-        }
-
-        if (aTimer.isTimeUp()) {
-            return getString(R.string.message_time_is_up);
-        }
-
-        int aMinutesLeft = aTimer.getMinutesLeft();
-
-        return getResources().getQuantityString(R.plurals.mask_timer_progress, aMinutesLeft, aMinutesLeft);
-    }
-
-    private void startTimer(int aMinutesLength) {
-        Timer aTimer = mCommunicationService.getSlideShow().getTimer();
-
-        aTimer.setMinutesLength(aMinutesLength);
-        aTimer.start();
-    }
-
-    private void changeTimer(int aMinutesLength) {
-        Timer aTimer = mCommunicationService.getSlideShow().getTimer();
-
-        if (aTimer.isTimeUp()) {
-            aTimer.reset();
-        }
-
-        aTimer.setMinutesLength(aMinutesLength);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        setUpSlideShowInformation();
-    }
-
-    @Override
-    public boolean onKeyDown(int aKeyCode, KeyEvent aKeyEvent) {
-        if (!areVolumeKeysActionsRequired()) {
-            return super.onKeyDown(aKeyCode, aKeyEvent);
-        }
-
-        switch (aKeyCode) {
-            case KeyEvent.KEYCODE_VOLUME_UP:
-                if (!isLastSlideDisplayed()) {
-                    mCommunicationService.getCommandsTransmitter().performNextTransition();
-                }
-                return true;
-
-            case KeyEvent.KEYCODE_VOLUME_DOWN:
-                mCommunicationService.getCommandsTransmitter().performPreviousTransition();
-                return true;
-
-            default:
-                return super.onKeyDown(aKeyCode, aKeyEvent);
-        }
-    }
-
-    private boolean areVolumeKeysActionsRequired() {
-        Preferences aPreferences = Preferences.getSettingsInstance(this);
-
-        return aPreferences.getBoolean(Preferences.Keys.VOLUME_KEYS_ACTIONS);
-    }
-
-    private boolean isLastSlideDisplayed() {
-        int aCurrentSlideIndex = mCommunicationService.getSlideShow().getHumanCurrentSlideIndex();
-        int aSlidesCount = mCommunicationService.getSlideShow().getSlidesCount();
-
-        return aCurrentSlideIndex == aSlidesCount;
-    }
-
-    @Override
-    public boolean onKeyUp(int aKeyCode, KeyEvent aKeyEvent) {
-        if (!areVolumeKeysActionsRequired()) {
-            return super.onKeyUp(aKeyCode, aKeyEvent);
-        }
-
-        // Suppress sound of volume changing
-
-        switch (aKeyCode) {
-            case KeyEvent.KEYCODE_VOLUME_UP:
-            case KeyEvent.KEYCODE_VOLUME_DOWN:
-                return true;
-
-            default:
-                return super.onKeyUp(aKeyCode, aKeyEvent);
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu aMenu) {
-        getSupportMenuInflater().inflate(R.menu.menu_action_bar_slide_show, aMenu);
-
-        return true;
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(Menu aMenu) {
-        MenuItem aSlidesPagerMenuItem = aMenu.findItem(R.id.menu_slides_pager);
-        MenuItem aSlidesGridMenuItem = aMenu.findItem(R.id.menu_slides_grid);
-        MenuItem aSlideShowResumeMenuItem = aMenu.findItem(R.id.menu_resume_slide_show);
-
-        switch (mMode) {
-            case PAGER:
-                setMenuItemsVisibility(aMenu, true);
-                aSlidesPagerMenuItem.setVisible(false);
-                aSlidesGridMenuItem.setVisible(true);
-                aSlideShowResumeMenuItem.setVisible(false);
-                break;
-
-            case GRID:
-                setMenuItemsVisibility(aMenu, true);
-                aSlidesPagerMenuItem.setVisible(true);
-                aSlidesGridMenuItem.setVisible(false);
-                aSlideShowResumeMenuItem.setVisible(false);
-                break;
-
-            case EMPTY:
-                setMenuItemsVisibility(aMenu, false);
-                aSlideShowResumeMenuItem.setVisible(true);
-                break;
-
-            default:
-                break;
-        }
-
-        return super.onPrepareOptionsMenu(aMenu);
-    }
-
-    private void setMenuItemsVisibility(Menu aMenu, boolean aAreItemsVisible) {
-        for (int aItemIndex = 0; aItemIndex < aMenu.size(); aItemIndex++) {
-            aMenu.getItem(aItemIndex).setVisible(aAreItemsVisible);
-        }
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem aMenuItem) {
-        switch (aMenuItem.getItemId()) {
-            case android.R.id.home:
-                navigateUp();
-                return true;
-
-            case R.id.menu_slides_grid:
-                changeMode(Mode.GRID);
-                return true;
-
-            case R.id.menu_slides_pager:
-                changeMode(Mode.PAGER);
-                return true;
-
-            case R.id.menu_timer:
-                callTimer();
-                return true;
-
-            case R.id.menu_resume_slide_show:
-                changeMode(Mode.PAGER);
-                setUpSlideShowInformation();
-                resumeSlideShow();
-                resumeTimer();
-                return true;
-
-            case R.id.menu_pause_slide_show:
-                changeMode(Mode.EMPTY);
-                setUpSlideShowPausedInformation();
-                pauseSlideShow();
-                pauseTimer();
-                return true;
-
-            case R.id.menu_stop_slide_show:
-                stopSlideShow();
-                return true;
-
-            default:
-                return super.onOptionsItemSelected(aMenuItem);
-        }
-    }
-
-    private void navigateUp() {
-        finish();
-    }
-
-    private void changeMode(Mode aMode) {
-        mMode = aMode;
-
-        setUpFragment();
-        refreshActionBarMenu();
-    }
-
-    private void refreshActionBarMenu() {
-        supportInvalidateOptionsMenu();
-    }
-
-    private void callTimer() {
-        Timer aTimer = mCommunicationService.getSlideShow().getTimer();
-
-        if (aTimer.isSet()) {
-            callEditingTimer(aTimer);
-        } else {
-            callSettingTimer();
-        }
-    }
-
-    private void callEditingTimer(Timer aTimer) {
-        DialogFragment aTimerDialog = buildTimerEditingDialog(aTimer);
-        aTimerDialog.show(getSupportFragmentManager(), TimerEditingDialog.TAG);
-
-        pauseTimer();
-    }
-
-    private DialogFragment buildTimerEditingDialog(Timer aTimer) {
-        if (aTimer.isTimeUp()) {
-            return TimerEditingDialog.newInstance(aTimer.getMinutesLength());
-        } else {
-            return TimerEditingDialog.newInstance(aTimer.getMinutesLeft());
-        }
-    }
-
-    private void callSettingTimer() {
-        DialogFragment aTimerDialog = TimerSettingDialog.newInstance();
-        aTimerDialog.show(getSupportFragmentManager(), TimerSettingDialog.TAG);
-    }
-
-    private void resumeSlideShow() {
-        mCommunicationService.getCommandsTransmitter().resumePresentation();
-    }
-
-    private void pauseSlideShow() {
-        mCommunicationService.getCommandsTransmitter().setUpBlankScreen();
-    }
-
-    private void setUpSlideShowPausedInformation() {
-        ActionBar aActionBar = getSupportActionBar();
-
-        aActionBar.setTitle(R.string.title_slide_show);
-        aActionBar.setSubtitle(R.string.message_paused);
-    }
-
-    private void pauseTimer() {
-        mCommunicationService.getSlideShow().getTimer().pause();
-    }
-
-    private void stopSlideShow() {
-        mCommunicationService.getCommandsTransmitter().stopPresentation();
-
-        finish();
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-
-        unregisterIntentsReceiver();
-    }
-
-    private void unregisterIntentsReceiver() {
-        try {
-            getBroadcastManager().unregisterReceiver(mIntentsReceiver);
-        } catch (IllegalArgumentException e) {
-            // Receiver not registered.
-            // Fixed in Honeycomb: Android’s issue #6191.
-        }
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle aOutState) {
-        super.onSaveInstanceState(aOutState);
-
-        saveMode(aOutState);
-    }
-
-    private void saveMode(Bundle aOutState) {
-        aOutState.putSerializable(SavedStates.Keys.MODE, mMode);
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-
-        if (!isServiceBound()) {
-            return;
-        }
-
-        unbindService();
-    }
-
-    private void unbindService() {
-        unbindService(this);
-    }
-
-    @Override
-    public void onServiceDisconnected(ComponentName aComponentName) {
-        mCommunicationService = null;
-    }
+public class SlideShowActivity extends SherlockFragmentActivity implements
+		ServiceConnection {
+	private static enum Mode {
+		PAGER, GRID, EMPTY
+	}
+
+	private Mode mMode;
+
+	private CommunicationService mCommunicationService;
+	private IntentsReceiver mIntentsReceiver;
+	private AudioManager audioManager;
+	private int ringerMode;
+
+	@Override
+	protected void onCreate(Bundle aSavedInstanceState) {
+		super.onCreate(aSavedInstanceState);
+
+		mMode = loadMode(aSavedInstanceState);
+
+		setUpHomeButton();
+		setUpFragment();
+		setUpKeepingScreenOn();
+		setUpKeepingSilentModeOn();
+
+		bindService();
+	}
+
+	private Mode loadMode(Bundle aSavedInstanceState) {
+		if (aSavedInstanceState == null) {
+			return Mode.PAGER;
+		}
+
+		return (Mode) aSavedInstanceState
+				.getSerializable(SavedStates.Keys.MODE);
+	}
+
+	private void setUpHomeButton() {
+		getSupportActionBar().setHomeButtonEnabled(true);
+	}
+
+	private void setUpFragment() {
+		FragmentOperator.replaceFragmentAnimated(this, buildFragment());
+	}
+
+	private Fragment buildFragment() {
+		switch (mMode) {
+		case PAGER:
+			return SlidesPagerFragment.newInstance();
+
+		case GRID:
+			return SlidesGridFragment.newInstance();
+
+		case EMPTY:
+			return EmptySlideFragment.newInstance();
+
+		default:
+			return SlidesPagerFragment.newInstance();
+		}
+	}
+
+	private void setUpKeepingScreenOn() {
+		findViewById(android.R.id.content).setKeepScreenOn(
+				isKeepingScreenOnRequired());
+	}
+
+	private boolean isKeepingScreenOnRequired() {
+		Preferences aPreferences = Preferences.getSettingsInstance(this);
+
+		return aPreferences.getBoolean(Preferences.Keys.KEEP_SCREEN_ON);
+	}
+	
+	private void setUpKeepingSilentModeOn() {
+		audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+		ringerMode = audioManager.getRingerMode();
+		if (!isKeepingSilentModeOnRequired()) {
+			audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
+		} else {
+			audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+		}
+	}
+
+	private boolean isKeepingSilentModeOnRequired() {
+		Preferences aPreferences = Preferences.getSettingsInstance(this);
+
+		return aPreferences.getBoolean(Preferences.Keys.KEEP_SILENT_MODE_ON);
+	}
+
+	private void bindService() {
+		Intent aIntent = Intents.buildCommunicationServiceIntent(this);
+		bindService(aIntent, this, Context.BIND_AUTO_CREATE);
+	}
+
+	@Override
+	public void onServiceConnected(ComponentName mComponentName, IBinder aBinder) {
+		CommunicationService.CBinder aServiceBinder = (CommunicationService.CBinder) aBinder;
+		mCommunicationService = aServiceBinder.getService();
+
+		startSlideShow();
+	}
+
+	private void startSlideShow() {
+		mCommunicationService.getTransmitter().startPresentation();
+	}
+
+	@Override
+	protected void onStart() {
+		super.onStart();
+
+		registerIntentsReceiver();
+	}
+
+	private void registerIntentsReceiver() {
+		mIntentsReceiver = new IntentsReceiver(this);
+		IntentFilter aIntentFilter = buildIntentsReceiverFilter();
+
+		getBroadcastManager().registerReceiver(mIntentsReceiver, aIntentFilter);
+	}
+
+	private static final class IntentsReceiver extends BroadcastReceiver {
+		private final SlideShowActivity mSlideShowActivity;
+
+		private IntentsReceiver(SlideShowActivity aSlideShowActivity) {
+			mSlideShowActivity = aSlideShowActivity;
+		}
+
+		@Override
+		public void onReceive(Context aContext, Intent aIntent) {
+			if (Intents.Actions.SLIDE_CHANGED.equals(aIntent.getAction())) {
+				mSlideShowActivity.setUpSlideShowInformation();
+				return;
+			}
+
+			if (Intents.Actions.TIMER_UPDATED.equals(aIntent.getAction())) {
+				mSlideShowActivity.setUpSlideShowInformation();
+				return;
+			}
+
+			if (Intents.Actions.TIMER_STARTED.equals(aIntent.getAction())) {
+				int aMinutesLength = aIntent.getIntExtra(
+						Intents.Extras.MINUTES, 0);
+				mSlideShowActivity.startTimer(aMinutesLength);
+				mSlideShowActivity.setUpSlideShowInformation();
+				return;
+			}
+
+			if (Intents.Actions.TIMER_RESUMED.equals(aIntent.getAction())) {
+				mSlideShowActivity.resumeTimer();
+				return;
+			}
+
+			if (Intents.Actions.TIMER_CHANGED.equals(aIntent.getAction())) {
+				int aMinutesLength = aIntent.getIntExtra(
+						Intents.Extras.MINUTES, 0);
+				mSlideShowActivity.changeTimer(aMinutesLength);
+				mSlideShowActivity.resumeTimer();
+				mSlideShowActivity.setUpSlideShowInformation();
+			}
+		}
+	}
+
+	private IntentFilter buildIntentsReceiverFilter() {
+		IntentFilter aIntentFilter = new IntentFilter();
+		aIntentFilter.addAction(Intents.Actions.SLIDE_CHANGED);
+		aIntentFilter.addAction(Intents.Actions.TIMER_UPDATED);
+		aIntentFilter.addAction(Intents.Actions.TIMER_STARTED);
+		aIntentFilter.addAction(Intents.Actions.TIMER_RESUMED);
+		aIntentFilter.addAction(Intents.Actions.TIMER_CHANGED);
+
+		return aIntentFilter;
+	}
+
+	private LocalBroadcastManager getBroadcastManager() {
+		return LocalBroadcastManager.getInstance(getApplicationContext());
+	}
+
+	private void setUpSlideShowInformation() {
+		if (!isServiceBound()) {
+			return;
+		}
+
+		ActionBar aActionBar = getSupportActionBar();
+
+		aActionBar.setTitle(buildSlideShowProgress());
+		aActionBar.setSubtitle(buildSlideShowTimerProgress());
+	}
+
+	private boolean isServiceBound() {
+		return mCommunicationService != null;
+	}
+
+	private String buildSlideShowProgress() {
+		SlideShow aSlideShow = mCommunicationService.getSlideShow();
+
+		int aCurrentSlideIndex = aSlideShow.getHumanCurrentSlideIndex();
+		int aSlidesCount = aSlideShow.getSlidesCount();
+
+		return getString(R.string.mask_slide_show_progress, aCurrentSlideIndex,
+				aSlidesCount);
+	}
+
+	private String buildSlideShowTimerProgress() {
+		Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+		if (!aTimer.isSet()) {
+			return null;
+		}
+
+		if (aTimer.isTimeUp()) {
+			return getString(R.string.message_time_is_up);
+		}
+
+		int aMinutesLeft = aTimer.getMinutesLeft();
+
+		return getResources().getQuantityString(R.plurals.mask_timer_progress,
+				aMinutesLeft, aMinutesLeft);
+	}
+
+	private void startTimer(int aMinutesLength) {
+		Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+		aTimer.setMinutesLength(aMinutesLength);
+		aTimer.start();
+	}
+
+	private void resumeTimer() {
+		mCommunicationService.getSlideShow().getTimer().resume();
+	}
+
+	private void changeTimer(int aMinutesLength) {
+		Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+		aTimer.setMinutesLength(aMinutesLength);
+	}
+
+	@Override
+	protected void onResume() {
+		super.onResume();
+
+		setUpSlideShowInformation();
+	}
+
+	@Override
+	public boolean onKeyDown(int aKeyCode, KeyEvent aKeyEvent) {
+		if (!areVolumeKeysActionsRequired()) {
+			return super.onKeyDown(aKeyCode, aKeyEvent);
+		}
+
+		switch (aKeyCode) {
+		case KeyEvent.KEYCODE_VOLUME_UP:
+			if (!isLastSlideDisplayed()) {
+				mCommunicationService.getTransmitter().performNextTransition();
+			}
+			return true;
+
+		case KeyEvent.KEYCODE_VOLUME_DOWN:
+			mCommunicationService.getTransmitter().performPreviousTransition();
+			return true;
+
+		default:
+			return super.onKeyDown(aKeyCode, aKeyEvent);
+		}
+	}
+
+	private boolean areVolumeKeysActionsRequired() {
+		Preferences aPreferences = Preferences.getSettingsInstance(this);
+
+		return aPreferences.getBoolean(Preferences.Keys.VOLUME_KEYS_ACTIONS);
+	}
+
+	private boolean isLastSlideDisplayed() {
+		int aCurrentSlideIndex = mCommunicationService.getSlideShow()
+				.getHumanCurrentSlideIndex();
+		int aSlidesCount = mCommunicationService.getSlideShow()
+				.getSlidesCount();
+
+		return aCurrentSlideIndex == aSlidesCount;
+	}
+
+	@Override
+	public boolean onKeyUp(int aKeyCode, KeyEvent aKeyEvent) {
+		if (!areVolumeKeysActionsRequired()) {
+			return super.onKeyUp(aKeyCode, aKeyEvent);
+		}
+
+		// Suppress sound of volume changing
+
+		switch (aKeyCode) {
+		case KeyEvent.KEYCODE_VOLUME_UP:
+		case KeyEvent.KEYCODE_VOLUME_DOWN:
+			return true;
+
+		default:
+			return super.onKeyUp(aKeyCode, aKeyEvent);
+		}
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(Menu aMenu) {
+		getSupportMenuInflater().inflate(R.menu.menu_action_bar_slide_show,
+				aMenu);
+
+		return true;
+	}
+
+	@Override
+	public boolean onPrepareOptionsMenu(Menu aMenu) {
+		MenuItem aSlidesPagerMenuItem = aMenu.findItem(R.id.menu_slides_pager);
+		MenuItem aSlidesGridMenuItem = aMenu.findItem(R.id.menu_slides_grid);
+		MenuItem aSlideShowResumeMenuItem = aMenu
+				.findItem(R.id.menu_resume_slide_show);
+
+		switch (mMode) {
+		case PAGER:
+			setMenuItemsVisibility(aMenu, true);
+			aSlidesPagerMenuItem.setVisible(false);
+			aSlidesGridMenuItem.setVisible(true);
+			aSlideShowResumeMenuItem.setVisible(false);
+			break;
+
+		case GRID:
+			setMenuItemsVisibility(aMenu, true);
+			aSlidesPagerMenuItem.setVisible(true);
+			aSlidesGridMenuItem.setVisible(false);
+			aSlideShowResumeMenuItem.setVisible(false);
+			break;
+
+		case EMPTY:
+			setMenuItemsVisibility(aMenu, false);
+			aSlideShowResumeMenuItem.setVisible(true);
+			break;
+
+		default:
+			break;
+		}
+
+		return super.onPrepareOptionsMenu(aMenu);
+	}
+
+	private void setMenuItemsVisibility(Menu aMenu, boolean aAreItemsVisible) {
+		for (int aItemIndex = 0; aItemIndex < aMenu.size(); aItemIndex++) {
+			aMenu.getItem(aItemIndex).setVisible(aAreItemsVisible);
+		}
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem aMenuItem) {
+		switch (aMenuItem.getItemId()) {
+		case android.R.id.home:
+			navigateUp();
+			return true;
+
+		case R.id.menu_slides_grid:
+			changeMode(Mode.GRID);
+			return true;
+
+		case R.id.menu_slides_pager:
+			changeMode(Mode.PAGER);
+			return true;
+
+		case R.id.menu_timer:
+			callTimer();
+			return true;
+
+		case R.id.menu_resume_slide_show:
+			changeMode(Mode.PAGER);
+			setUpSlideShowInformation();
+			resumeSlideShow();
+			resumeTimer();
+			return true;
+
+		case R.id.menu_pause_slide_show:
+			changeMode(Mode.EMPTY);
+			setUpSlideShowPausedInformation();
+			pauseSlideShow();
+			pauseTimer();
+			return true;
+
+		case R.id.menu_stop_slide_show:
+			stopSlideShow();
+			return true;
+
+		default:
+			return super.onOptionsItemSelected(aMenuItem);
+		}
+	}
+
+	private void navigateUp() {
+		finish();
+	}
+
+	private void changeMode(Mode aMode) {
+		mMode = aMode;
+
+		setUpFragment();
+		refreshActionBarMenu();
+	}
+
+	private void refreshActionBarMenu() {
+		supportInvalidateOptionsMenu();
+	}
+
+	private void callTimer() {
+		Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+
+		if (aTimer.isSet()) {
+			callEditingTimer(aTimer);
+		} else {
+			callSettingTimer();
+		}
+	}
+
+	private void callEditingTimer(Timer aTimer) {
+		DialogFragment aTimerDialog = buildTimerEditingDialog(aTimer);
+		aTimerDialog.show(getSupportFragmentManager(), TimerEditingDialog.TAG);
+
+		aTimer.pause();
+	}
+
+	private DialogFragment buildTimerEditingDialog(Timer aTimer) {
+		if (aTimer.isTimeUp()) {
+			return TimerEditingDialog.newInstance(aTimer.getMinutesLength());
+		} else {
+			return TimerEditingDialog.newInstance(aTimer.getMinutesLeft());
+		}
+	}
+
+	private void callSettingTimer() {
+		DialogFragment aTimerDialog = TimerSettingDialog.newInstance();
+		aTimerDialog.show(getSupportFragmentManager(), TimerSettingDialog.TAG);
+	}
+
+	private void resumeSlideShow() {
+		mCommunicationService.getTransmitter().resumePresentation();
+	}
+
+	private void pauseSlideShow() {
+		mCommunicationService.getTransmitter().setUpBlankScreen();
+	}
+
+	private void setUpSlideShowPausedInformation() {
+		ActionBar aActionBar = getSupportActionBar();
+
+		aActionBar.setTitle(R.string.title_slide_show);
+		aActionBar.setSubtitle(R.string.message_paused);
+	}
+
+	private void pauseTimer() {
+		mCommunicationService.getSlideShow().getTimer().pause();
+	}
+
+	private void stopSlideShow() {
+		mCommunicationService.getTransmitter().stopPresentation();
+		finish();
+	}
+
+	@Override
+	protected void onStop() {
+		super.onStop();
+		audioManager.setRingerMode(ringerMode);
+		unregisterIntentsReceiver();
+	}
+
+	private void unregisterIntentsReceiver() {
+		try {
+			getBroadcastManager().unregisterReceiver(mIntentsReceiver);
+		} catch (IllegalArgumentException e) {
+			// Receiver not registered.
+			// Fixed in Honeycomb: Android’s issue #6191.
+		}
+	}
+
+	@Override
+	protected void onSaveInstanceState(Bundle aOutState) {
+		super.onSaveInstanceState(aOutState);
+
+		saveMode(aOutState);
+	}
+
+	private void saveMode(Bundle aOutState) {
+		aOutState.putSerializable(SavedStates.Keys.MODE, mMode);
+	}
+
+	@Override
+	protected void onDestroy() {
+		super.onDestroy();
+
+		if (!isServiceBound()) {
+			return;
+		}
+
+		stopTimer();
+
+		// TODO: disconnect computer
+
+		unbindService();
+	}
+
+	private void stopTimer() {
+		mCommunicationService.getSlideShow().getTimer().stop();
+	}
+
+	private void unbindService() {
+		unbindService(this);
+	}
+
+	@Override
+	public void onServiceDisconnected(ComponentName aComponentName) {
+		mCommunicationService = null;
+	}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/sdremote/src/org/libreoffice/impressremote/util/Preferences.java b/android/sdremote/src/org/libreoffice/impressremote/util/Preferences.java
index 5a9b0c7..700b60a 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/util/Preferences.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/util/Preferences.java
@@ -32,6 +32,7 @@ public final class Preferences {
 
         public static final String VOLUME_KEYS_ACTIONS = "volume_keys_actions";
         public static final String KEEP_SCREEN_ON = "keep_screen_on";
+        public static final String KEEP_SILENT_MODE_ON = "keep_silent_mode_on";
     }
 
     private static final class Defaults {
@@ -45,20 +46,16 @@ public final class Preferences {
 
     private final SharedPreferences mPreferences;
 
-    private Preferences(Context context) {
-        mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+    public static Preferences getAuthorizedServersInstance(Context aContext) {
+        return new Preferences(aContext, Locations.AUTHORIZED_SERVERS);
     }
 
     private Preferences(Context aContext, String aLocation) {
-        mPreferences = aContext.getSharedPreferences(aLocation, Context.MODE_PRIVATE);
+        mPreferences = getPreferences(aContext, aLocation);
     }
 
-    public static Preferences getSettingsInstance(Context context) {
-        return new Preferences(context);
-    }
-
-    public static Preferences getAuthorizedServersInstance(Context aContext) {
-        return new Preferences(aContext, Locations.AUTHORIZED_SERVERS);
+    private SharedPreferences getPreferences(Context aContext, String aLocation) {
+        return aContext.getSharedPreferences(aLocation, Context.MODE_PRIVATE);
     }
 
     public static Preferences getSavedServersInstance(Context aContext) {
@@ -69,30 +66,38 @@ public final class Preferences {
         return new Preferences(aContext, Locations.APPLICATION_STATES);
     }
 
-    public Map<String, ?> getAll() {
-        return mPreferences.getAll();
+    public static Preferences getSettingsInstance(Context context) {
+        return new Preferences(context);
     }
 
-    public boolean getBoolean(String aKey) {
-        return mPreferences.getBoolean(aKey, Defaults.BOOLEAN);
+    private Preferences(Context context) {
+        mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
     }
 
-    public int getInt(String aKey) {
-        return mPreferences.getInt(aKey, Defaults.INT);
+    public Map<String, ?> getAll() {
+        return mPreferences.getAll();
     }
 
     public String getString(String aKey) {
         return mPreferences.getString(aKey, Defaults.STRING);
     }
 
-    public void setInt(String aKey, int aValue) {
-        mPreferences.edit().putInt(aKey, aValue).commit();
+    public int getInt(String aKey) {
+        return mPreferences.getInt(aKey, Defaults.INT);
     }
 
     public void setString(String aKey, String aValue) {
         mPreferences.edit().putString(aKey, aValue).commit();
     }
 
+    public boolean getBoolean(String aKey) {
+        return mPreferences.getBoolean(aKey, Defaults.BOOLEAN);
+    }
+
+    public void setInt(String aKey, int aValue) {
+        mPreferences.edit().putInt(aKey, aValue).commit();
+    }
+
     public void remove(String aKey) {
         mPreferences.edit().remove(aKey).commit();
     }
-- 
1.7.10.4

