android/sdremote/AndroidManifest.xml                                           
            |    1 
 android/sdremote/res/layout/activity_thumbnail.xml                             
            |   13 
 android/sdremote/res/layout/slide_thumbnail.xml                                
            |   21 +
 android/sdremote/res/layout/testlayout.xml                                     
            |    7 
 android/sdremote/src/org/libreoffice/impressremote/TestClient.java             
            |   52 +-
 android/sdremote/src/org/libreoffice/impressremote/ThumbnailActivity.java      
            |  185 ++++++++++
 
android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
 |   12 
 android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java 
            |   72 ++-
 
android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java 
           |   37 ++
 sd/source/ui/inc/Server.hxx                                                    
            |    2 
 sd/source/ui/remotecontrol/ImagePreparer.cxx                                   
            |  154 ++++++++
 sd/source/ui/remotecontrol/ImagePreparer.hxx                                   
            |   51 ++
 sd/source/ui/remotecontrol/Listener.cxx                                        
            |   27 +
 sd/source/ui/remotecontrol/Listener.hxx                                        
            |    6 
 sd/source/ui/remotecontrol/Server.cxx                                          
            |   21 -
 sd/source/ui/slideshow/slideshow.cxx                                           
            |    2 
 sd/source/ui/slideshow/slideshowimpl.cxx                                       
            |    4 
 17 files changed, 609 insertions(+), 58 deletions(-)

New commits:
commit d4098f9eabb29e470890139f6679be445c016896
Author: Andrzej J. R. Hunt <andr...@ahunt.org>
Date:   Fri Jul 20 17:50:10 2012 +0200

    Implemented Thumbnail activity.
    
    Change-Id: I I6de8651f3ed36798ca1cc69765c448b821a819a2

diff --git a/android/sdremote/AndroidManifest.xml 
b/android/sdremote/AndroidManifest.xml
index 82cb1be..e136ca3 100644
--- a/android/sdremote/AndroidManifest.xml
+++ b/android/sdremote/AndroidManifest.xml
@@ -22,6 +22,7 @@
 
         <service android:name=".communication.CommunicationService" >
         </service>
+        <activity android:name=".ThumbnailActivity"></activity>
     </application>
 
 </manifest>
\ No newline at end of file
diff --git a/android/sdremote/res/layout/activity_thumbnail.xml 
b/android/sdremote/res/layout/activity_thumbnail.xml
new file mode 100644
index 0000000..068ab78
--- /dev/null
+++ b/android/sdremote/res/layout/activity_thumbnail.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<GridView xmlns:android="http://schemas.android.com/apk/res/android";
+    android:id="@+id/thumbnail_grid"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:columnWidth="90dp"
+    android:gravity="center"
+    android:horizontalSpacing="10dp"
+    android:numColumns="auto_fit"
+    android:stretchMode="columnWidth"
+    android:verticalSpacing="10dp" >
+
+</GridView>
\ No newline at end of file
diff --git a/android/sdremote/res/layout/slide_thumbnail.xml 
b/android/sdremote/res/layout/slide_thumbnail.xml
new file mode 100644
index 0000000..448b3ed
--- /dev/null
+++ b/android/sdremote/res/layout/slide_thumbnail.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android";
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <ImageView
+        android:id="@+id/sub_thumbnail"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:src="@drawable/ic_launcher" />
+
+    <TextView
+        android:id="@+id/sub_number"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="0" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/android/sdremote/res/layout/testlayout.xml 
b/android/sdremote/res/layout/testlayout.xml
index 8e7a4f1..4f0b065 100644
--- a/android/sdremote/res/layout/testlayout.xml
+++ b/android/sdremote/res/layout/testlayout.xml
@@ -25,6 +25,13 @@
         android:layout_gravity="center_horizontal"
         android:text="Previous" />
 
+    <Button
+        android:id="@+id/button_thumbnail"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="Thumbnail View" />
+
     <ImageView
         android:id="@+id/image_preview"
         android:layout_width="wrap_content"
diff --git a/android/sdremote/src/org/libreoffice/impressremote/TestClient.java 
b/android/sdremote/src/org/libreoffice/impressremote/TestClient.java
index 627d885..99b3fad 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/TestClient.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/TestClient.java
@@ -52,6 +52,13 @@ public class TestClient extends Activity {
        protected void onPause() {
                super.onPause();
                doUnbindService();
+       }
+
+       @Override
+       protected void onStop() {
+               // TODO Auto-generated method stub
+               super.onStop();
+//             mCommunicationService.disconnect();
                stopService(new Intent(this, CommunicationService.class));
        }
 
@@ -75,13 +82,14 @@ public class TestClient extends Activity {
        };
 
        void doBindService() {
-               bindService(new Intent(this, CommunicationService.class), 
mConnection,
-                               Context.BIND_AUTO_CREATE);
+               Intent aIntent = new Intent(this, CommunicationService.class);
+               startService(aIntent);
+               bindService(aIntent, mConnection,
+                               Context.BIND_IMPORTANT);
                mIsBound = true;
        }
 
        void doUnbindService() {
-               mCommunicationService.disconnect();
                mCommunicationService.setActivityMessenger(null);
                if (mIsBound) {
                        unbindService(mConnection);
@@ -125,6 +133,16 @@ public class TestClient extends Activity {
 
                });
 
+               Button mThumbnailButton = (Button) 
findViewById(R.id.button_thumbnail);
+
+               mThumbnailButton.setOnClickListener(new OnClickListener() {
+                       @Override
+                       public void onClick(View v) {
+                               Intent aIntent = new Intent(TestClient.this, 
ThumbnailActivity.class);
+                               startActivity( aIntent);
+                       }
+               });
+
        }
 
        private void enableButtons(boolean aEnabled) {
@@ -146,7 +164,7 @@ public class TestClient extends Activity {
                                int aSlideNumber = aData.getInt("slide_number");
                                if ( mCurrentPreviewImageMissing ) {
                                        Bitmap aImage = mCommunicationService
-                                                       
.getPreviewImage(aSlideNumber);
+                                                       
.getSlideShow().getImage(aSlideNumber);
                                        if (aImage != null) {
                                                
mImageView.setImageBitmap(aImage);
                                                mCurrentPreviewImageMissing = 
false;
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/ThumbnailActivity.java 
b/android/sdremote/src/org/libreoffice/impressremote/ThumbnailActivity.java
new file mode 100644
index 0000000..ce39e0c
--- /dev/null
+++ b/android/sdremote/src/org/libreoffice/impressremote/ThumbnailActivity.java
@@ -0,0 +1,185 @@
+package org.libreoffice.impressremote;
+
+import org.libreoffice.impressremote.TestClient.MessageHandler;
+import org.libreoffice.impressremote.communication.CommunicationService;
+import org.libreoffice.impressremote.communication.SlideShow;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class ThumbnailActivity extends Activity {
+
+       private CommunicationService mCommunicationService;
+       private boolean mIsBound = false;
+
+       private GridView mGrid;
+       private ImageView mCurrentImage;
+       private TextView mCurrentText;
+
+       private SlideShow mSlideShow;
+
+       @Override
+       public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+               setContentView(R.layout.activity_thumbnail);
+
+               bindService(new Intent(this, CommunicationService.class), 
mConnection,
+                               Context.BIND_ADJUST_WITH_ACTIVITY);
+               mIsBound = true;
+
+               mGrid = (GridView) findViewById(R.id.thumbnail_grid);
+
+               mGrid.setOnItemClickListener(new ClickListener());
+       }
+
+       @Override
+       protected void onPause() {
+               super.onPause();
+               mCommunicationService.setActivityMessenger(null);
+               if (mIsBound) {
+                       unbindService(mConnection);
+                       mIsBound = false;
+               }
+       }
+
+       private void setSelected(int position) {
+               if (mCurrentImage != null) {
+                       mCurrentImage.setPadding(0, 0, 0, 0);
+               }
+               if (mCurrentText != null) {
+                       mCurrentText.setTypeface(Typeface.create(
+                                       mCurrentText.getTypeface(), 
Typeface.NORMAL));
+               }
+
+               View aV = mGrid.getChildAt(position);
+               if (aV != null) {
+                       mCurrentImage = (ImageView) 
aV.findViewById(R.id.sub_thumbnail);
+                       mCurrentText = (TextView) 
aV.findViewById(R.id.sub_number);
+
+                       mCurrentImage.setBackgroundColor(Color.RED);
+                       mCurrentImage.setPadding(2, 2, 2, 2);
+                       
mCurrentText.setTypeface(Typeface.create(mCurrentText.getTypeface(),
+                                       Typeface.BOLD));
+               }
+       }
+
+       // ------------------------------------------------- SERVICE CONNECTION 
----
+       final Messenger mMessenger = new Messenger(new MessageHandler());
+
+       private ServiceConnection mConnection = new ServiceConnection() {
+               @Override
+               public void onServiceConnected(ComponentName aClassName,
+                               IBinder aService) {
+                       mCommunicationService = ((CommunicationService.CBinder) 
aService)
+                                       .getService();
+                       mCommunicationService.setActivityMessenger(mMessenger);
+                       mSlideShow = mCommunicationService.getSlideShow();
+                       mGrid.setAdapter(new 
ThumbnailAdapter(ThumbnailActivity.this,
+                                       mSlideShow));
+               }
+
+               @Override
+               public void onServiceDisconnected(ComponentName aClassName) {
+                       mCommunicationService = null;
+               }
+       };
+
+       // ----------------------------------------------------- CLICK LISTENER 
----
+       protected class ClickListener implements 
AdapterView.OnItemClickListener {
+               public void onItemClick(AdapterView<?> parent, View v, int 
position,
+                               long id) {
+                       
mCommunicationService.getTransmitter().gotoSlide(position);
+               }
+       }
+
+       // ---------------------------------------------------- MESSAGE HANDLER 
----
+       protected class MessageHandler extends Handler {
+               @Override
+               public void handleMessage(Message aMessage) {
+                       Bundle aData = aMessage.getData();
+                       switch (aMessage.what) {
+                       case CommunicationService.MSG_SLIDE_CHANGED:
+                               int aSlide = aData.getInt("slide_number");
+                               setSelected(aSlide);
+                               break;
+                       case CommunicationService.MSG_SLIDE_PREVIEW:
+                               // int aNSlide = aData.getInt("slide_number");
+                               mGrid.invalidateViews();
+                               break;
+
+                       }
+               }
+       }
+
+       // ------------------------------------------------- THUMBNAIL ADAPTER 
----
+       protected class ThumbnailAdapter extends BaseAdapter {
+
+               private Context mContext;
+
+               private SlideShow mSlideShow;
+
+               public ThumbnailAdapter(Context aContext, SlideShow aSlideShow) 
{
+                       mContext = aContext;
+                       mSlideShow = aSlideShow;
+               }
+
+               @Override
+               public int getCount() {
+                       return mSlideShow.getSize();
+               }
+
+               @Override
+               public Object getItem(int arg0) {
+                       return null;
+               }
+
+               @Override
+               public long getItemId(int position) {
+                       return 0;
+               }
+
+               @Override
+               public View getView(int position, View convertView, ViewGroup 
parent) {
+                       LayoutInflater aInflater = (LayoutInflater) mContext
+                                       
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                       View v = aInflater.inflate(R.layout.slide_thumbnail, 
null);
+
+                       ImageView aImage = (ImageView) 
v.findViewById(R.id.sub_thumbnail);
+                       TextView aText = (TextView) 
v.findViewById(R.id.sub_number);
+
+                       Bitmap aBitmap = mSlideShow.getImage(position);
+                       if (aBitmap != null) {
+                               aImage.setImageBitmap(aBitmap);
+                       }
+
+                       aText.setText(String.valueOf(position + 1));
+
+//                     if ((mSlideShow != null)
+//                                     && (position == 
mSlideShow.getCurrentSlide())) {
+//                             setSelected(position);
+//                     }
+
+                       return v;
+               }
+
+       }
+}
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
 
b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
index ab2794a..48a8e7c 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
@@ -25,8 +25,9 @@ public class CommunicationService extends Service {
                NETWORK, BLUETOOTH
        };
 
-       public static final int MSG_SLIDE_CHANGED = 1;
-       public static final int MSG_SLIDE_PREVIEW = 2;
+       public static final int MSG_SLIDESHOW_STARTED = 1;
+       public static final int MSG_SLIDE_CHANGED = 2;
+       public static final int MSG_SLIDE_PREVIEW = 3;
 
        private Transmitter mTransmitter;
 
@@ -74,8 +75,8 @@ public class CommunicationService extends Service {
                mClient.closeConnection();
        }
 
-       public Bitmap getPreviewImage(int aSlide) {
-               return mReceiver.getPreviewImage(aSlide);
+       public SlideShow getSlideShow() {
+               return mReceiver.getSlideShow();
        }
 
 
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
 
b/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
index 05d26e0..1b2ffff 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
@@ -23,15 +23,14 @@ public class Receiver {
 
        private Messenger mActivityMessenger;
 
-       private SparseArray<byte[]> mPreviewImages = new SparseArray<byte[]>();
+       private SlideShow mSlideShow = null;
 
-       public void setActivityMessenger(Messenger aActivityMessenger) {
-               mActivityMessenger = aActivityMessenger;
+       public SlideShow getSlideShow() {
+               return mSlideShow;
        }
 
-       public Bitmap getPreviewImage(int aSlide) {
-               byte[] aImage = mPreviewImages.get(aSlide);
-               return BitmapFactory.decodeByteArray(aImage, 0, aImage.length);
+       public void setActivityMessenger(Messenger aActivityMessenger) {
+               mActivityMessenger = aActivityMessenger;
        }
 
        public void parseCommand(ArrayList<String> aCommand) {
@@ -40,37 +39,56 @@ public class Receiver {
                        return;
                }
                String aInstruction = aCommand.get(0);
-               if (aInstruction.equals("slide_updated")) {
-                       int aSlideNumber = Integer.parseInt(aCommand.get(1));
+               if (aInstruction.equals("slideshow_started")) {
+                       int aSlideShowlength = 
Integer.parseInt(aCommand.get(1));
+                       mSlideShow = new SlideShow(aSlideShowlength);
+
                        Message aMessage = Message.obtain(null,
-                                       CommunicationService.MSG_SLIDE_CHANGED);
+                                       
CommunicationService.MSG_SLIDESHOW_STARTED);
                        Bundle aData = new Bundle();
-                       aData.putInt("slide_number", aSlideNumber);
                        aMessage.setData(aData);
                        try {
                                mActivityMessenger.send(aMessage);
                        } catch (RemoteException e) {
                                // Dead Handler -- i.e. Activity gone.
                        }
-               } else if (aInstruction.equals("slide_preview")) {
-                       int aSlideNumber = Integer.parseInt(aCommand.get(1));
-                       String aImageString = aCommand.get(2);
-                       byte[] aImage = Base64.decode(aImageString, 
Base64.DEFAULT);
+               } else {
+                       if (mSlideShow == null)
+                               return;
 
-                       // Store image internally
-                       mPreviewImages.put(aSlideNumber, aImage);
+                       if (aInstruction.equals("slide_updated")) {
 
-                       // Notify the frontend
-                       Message aMessage = Message.obtain(null,
-                                       CommunicationService.MSG_SLIDE_PREVIEW);
-                       Bundle aData = new Bundle();
-                       aData.putInt("slide_number", aSlideNumber);
-                       aMessage.setData(aData);
-                       try {
-                               mActivityMessenger.send(aMessage);
-                       } catch (RemoteException e) {
-                               // TODO Auto-generated catch block
-                               e.printStackTrace();
+                               int aSlideNumber = 
Integer.parseInt(aCommand.get(1));
+                               Message aMessage = Message.obtain(null,
+                                               
CommunicationService.MSG_SLIDE_CHANGED);
+                               Bundle aData = new Bundle();
+                               aData.putInt("slide_number", aSlideNumber);
+                               aMessage.setData(aData);
+                               try {
+                                       mActivityMessenger.send(aMessage);
+                               } catch (RemoteException e) {
+                                       // Dead Handler -- i.e. Activity gone.
+                               }
+                       } else if (aInstruction.equals("slide_preview")) {
+                               int aSlideNumber = 
Integer.parseInt(aCommand.get(1));
+                               String aImageString = aCommand.get(2);
+                               byte[] aImage = Base64.decode(aImageString, 
Base64.DEFAULT);
+
+                               // Store image internally
+                               mSlideShow.putImage(aSlideNumber, aImage);
+
+                               // Notify the frontend
+                               Message aMessage = Message.obtain(null,
+                                               
CommunicationService.MSG_SLIDE_PREVIEW);
+                               Bundle aData = new Bundle();
+                               aData.putInt("slide_number", aSlideNumber);
+                               aMessage.setData(aData);
+                               try {
+                                       mActivityMessenger.send(aMessage);
+                               } catch (RemoteException e) {
+                                       // TODO Auto-generated catch block
+                                       e.printStackTrace();
+                               }
                        }
 
                }
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
 
b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
new file mode 100644
index 0000000..b65bcaf
--- /dev/null
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
@@ -0,0 +1,37 @@
+package org.libreoffice.impressremote.communication;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.SparseArray;
+
+public class SlideShow {
+
+       private SparseArray<byte[]> mPreviewImages = new SparseArray<byte[]>();
+       private int mSize = 0;
+       private int mCurrentSlide = 0;
+
+       protected SlideShow(int aSize) {
+               mSize = aSize;
+       }
+
+       public int getSize() {
+               return mSize;
+       }
+
+       public int getCurrentSlide() {
+               return mCurrentSlide;
+       }
+
+       protected void setCurrentSlide(int aSlide) {
+               mCurrentSlide = aSlide;
+       }
+
+       protected void putImage(int aSlide, byte[] aImage) {
+               mPreviewImages.put(aSlide, aImage);
+       }
+
+       public Bitmap getImage(int aSlide) {
+               byte[] aImage = mPreviewImages.get(aSlide);
+               return BitmapFactory.decodeByteArray(aImage, 0, aImage.length);
+       }
+}
diff --git a/sd/source/ui/remotecontrol/ImagePreparer.cxx 
b/sd/source/ui/remotecontrol/ImagePreparer.cxx
new file mode 100644
index 0000000..a42be1f
--- /dev/null
+++ b/sd/source/ui/remotecontrol/ImagePreparer.cxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "ImagePreparer.hxx"
+
+#include <comphelper/processfactory.hxx>
+#include <osl/file.hxx>
+#include <xmlsec/base64.h>
+#include <rtl/ustrbuf.hxx>
+#include <sax/tools/converter.hxx>
+#include <rtl/strbuf.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+
+using namespace sd;
+using namespace rtl;
+using namespace osl;
+using namespace ::com::sun::star;
+
+ImagePreparer::ImagePreparer(
+    const uno::Reference<presentation::XSlideShowController>& rxController,
+    Transmitter *aTransmitter, rtl::Reference<ImagePreparer>& rRef )
+ :  Thread( "ImagePreparer Thread" ),
+    xController( rxController ),
+    pTransmitter( aTransmitter ),
+    mRef( rRef )
+{
+}
+
+ImagePreparer::~ImagePreparer()
+{
+}
+
+void ImagePreparer::execute()
+{
+    fprintf( stderr, "ImagePreparer running\n" );
+    sal_uInt32 aSlides = xController->getSlideCount();
+    for ( sal_uInt32 i = 0; i < aSlides; i++ )
+    {
+        if ( !xController->isRunning() ) // stopped/disposed of.
+        {
+            break;
+        }
+        sendPreview( i );
+    }
+    fprintf( stderr, "ImagePreparer done\n" );
+    mRef.clear();
+}
+
+void ImagePreparer::sendPreview( sal_uInt32 aSlideNumber )
+{
+    sal_uInt64 aSize;
+    uno::Sequence<sal_Int8> aImageData = preparePreview( aSlideNumber, 160, 
120,
+        aSize );
+    if ( !xController->isRunning() )
+        return;
+
+    OUStringBuffer aStrBuffer;
+    ::sax::Converter::encodeBase64( aStrBuffer, aImageData );
+
+    OString aEncodedShortString = OUStringToOString(
+        aStrBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
+
+    // Start the writing
+    OStringBuffer aBuffer;
+
+    aBuffer.append( "slide_preview\n" );
+
+    aBuffer.append( OString::valueOf( sal_Int32( aSlideNumber ) ).getStr() );
+    aBuffer.append( "\n" );
+
+    aBuffer.append( aEncodedShortString.getStr() );
+    aBuffer.append( "\n\n" );
+    pTransmitter->addMessage( aBuffer.makeStringAndClear(),
+        Transmitter::Priority::LOW );
+
+}
+
+uno::Sequence<sal_Int8> ImagePreparer::preparePreview(
+    sal_uInt32 aSlideNumber, sal_uInt32 aWidth, sal_uInt32 aHeight,
+    sal_uInt64 &rSize )
+{
+    OUString aFileURL;
+    FileBase::createTempFile( 0, 0, &aFileURL );
+
+    uno::Reference< lang::XMultiServiceFactory > xServiceManager(
+        ::comphelper::getProcessServiceFactory(),
+        uno::UNO_QUERY_THROW );
+
+    uno::Reference< document::XFilter > xFilter(
+        xServiceManager->createInstance(
+        "com.sun.star.drawing.GraphicExportFilter" ) ,
+        uno::UNO_QUERY_THROW );
+
+    uno::Reference< document::XExporter > xExporter( xFilter,
+        uno::UNO_QUERY_THROW );
+
+    if ( !xController->isRunning() )
+        return uno::Sequence<sal_Int8>();
+    uno::Reference< lang::XComponent > xSourceDoc(
+        xController->getSlideByIndex( aSlideNumber ),
+        uno::UNO_QUERY_THROW );
+
+    xExporter->setSourceDocument( xSourceDoc );
+
+    uno::Sequence< beans::PropertyValue > aFilterData(3);
+
+    aFilterData[0].Name = "PixelWidth";
+    aFilterData[0].Value <<= aWidth;
+
+    aFilterData[1].Name = "PixelHeight";
+    aFilterData[1].Value <<= aHeight;
+
+    aFilterData[2].Name = "ColorMode";
+    aFilterData[2].Value <<= sal_Int32(0); // 0: Color, 1: B&W
+
+    uno::Sequence< beans::PropertyValue > aProps(3);
+
+    aProps[0].Name = "MediaType";
+    aProps[0].Value <<= OUString( "image/png" );
+
+    aProps[1].Name = "URL";
+    aProps[1].Value <<= aFileURL;
+
+    aProps[2].Name = "FilterData";
+    aProps[2].Value <<= aFilterData;
+
+    xFilter->filter( aProps );
+
+    // FIXME: error handling.
+
+    File aFile( aFileURL );
+    aFile.open(0);
+    sal_uInt64 aRead;
+    rSize = 0;
+    aFile.getSize( rSize );
+    uno::Sequence<sal_Int8> aContents( rSize );
+
+    aFile.read( aContents.getArray(), rSize, aRead );
+    aFile.close();
+    File::remove( aFileURL );
+    return aContents;
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
diff --git a/sd/source/ui/remotecontrol/ImagePreparer.hxx 
b/sd/source/ui/remotecontrol/ImagePreparer.hxx
new file mode 100644
index 0000000..7f193bb
--- /dev/null
+++ b/sd/source/ui/remotecontrol/ImagePreparer.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#ifndef _SD_IMPRESSREMOTE_IMAGEPREPARER_HXX
+#define _SD_IMPRESSREMOTE_IMAGEPREPARER_HXX
+
+#include <salhelper/thread.hxx>
+#include <rtl/ref.hxx>
+
+#include <com/sun/star/presentation/XSlideShowController.hpp>
+
+#include "Transmitter.hxx"
+
+namespace css = ::com::sun::star;
+
+namespace sd
+{
+
+class ImagePreparer:
+    public salhelper::Thread
+{
+public:
+    ImagePreparer( const
+        css::uno::Reference<css::presentation::XSlideShowController>&
+        rxController, sd::Transmitter *aTransmitter,
+        rtl::Reference<ImagePreparer>& rRef );
+    ~ImagePreparer();
+
+private:
+    css::uno::Reference<css::presentation::XSlideShowController> xController;
+    Transmitter *pTransmitter;
+    rtl::Reference<ImagePreparer>& mRef;
+
+    // Thread method
+    void execute();
+
+    void sendPreview( sal_uInt32 aSlideNumber );
+    css::uno::Sequence<sal_Int8> preparePreview( sal_uInt32 aSlideNumber,
+                sal_uInt32 aWidth, sal_uInt32 aHeight, sal_uInt64 &rSize );
+};
+
+}
+
+
+#endif // _SD_IMPRESSREMOTE_IMAGEPREPARER_HXX
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/remotecontrol/Listener.cxx 
b/sd/source/ui/remotecontrol/Listener.cxx
index 1f55710..3619905 100644
--- a/sd/source/ui/remotecontrol/Listener.cxx
+++ b/sd/source/ui/remotecontrol/Listener.cxx
@@ -48,6 +48,14 @@ void Listener::init( const css::uno::Reference< 
css::presentation::XSlideShowCon
         aController->addSlideShowListener( this );
         fprintf( stderr, "Registered listener.\n" );
 
+        sal_Int32 aSlides = aController->getSlideCount();
+        OStringBuffer aBuffer;
+        aBuffer.append( "slideshow_started\n" )
+               .append( OString::valueOf( aSlides ) ).append( "\n\n" );
+
+        pTransmitter->addMessage( aBuffer.makeStringAndClear(),
+                                  Transmitter::Priority::HIGH );
+
         mPreparer.set( new ImagePreparer( aController, pTransmitter, mPreparer 
) );
         mPreparer->launch();
     }
diff --git a/sd/source/ui/remotecontrol/Listener.hxx 
b/sd/source/ui/remotecontrol/Listener.hxx
index 92a0b93..1fc411d 100644
--- a/sd/source/ui/remotecontrol/Listener.hxx
+++ b/sd/source/ui/remotecontrol/Listener.hxx
@@ -26,6 +26,10 @@
 namespace css = ::com::sun::star;
 
 namespace sd {
+/**
+ * Slide show listener. This class can also be used for anything else that is
+ * specific to the lifetime of one slideshow while a client is connected.
+ */
 class Listener
     : protected ::cppu::BaseMutex,
       public ::cppu::WeakComponentImplHelper1< 
css::presentation::XSlideShowListener >
diff --git a/sd/source/ui/remotecontrol/Server.cxx 
b/sd/source/ui/remotecontrol/Server.cxx
index 0329e27..700e561 100644
--- a/sd/source/ui/remotecontrol/Server.cxx
+++ b/sd/source/ui/remotecontrol/Server.cxx
@@ -94,8 +94,7 @@ void Server::listenThread()
     }
     // TODO: deal with transmision errors gracefully.
     fprintf( stderr, "done with transmitting\n" );
-    mListener->disposing();
-    mListener = NULL;
+    presentationStopped();
 
     delete pTransmitter;
     pTransmitter = NULL;
commit 050b0d099edac2da6993e00dadcb43127680d48a
Author: Andrzej J. R. Hunt <andr...@ahunt.org>
Date:   Fri Jul 20 12:02:54 2012 +0200

    Fixed a further bug in the Listener cycle. Refactored image storage.
    
    Change-Id: I2b3f9e2c46dafde4bd488bc95675c04e8806c9a4

diff --git a/android/sdremote/src/org/libreoffice/impressremote/TestClient.java 
b/android/sdremote/src/org/libreoffice/impressremote/TestClient.java
index 4d716ad..627d885 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/TestClient.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/TestClient.java
@@ -1,7 +1,5 @@
 package org.libreoffice.impressremote;
 
-import java.util.HashMap;
-
 import org.libreoffice.impressremote.communication.CommunicationService;
 import android.app.Activity;
 import android.content.ComponentName;
@@ -23,11 +21,12 @@ import android.widget.TextView;
 
 public class TestClient extends Activity {
 
-       private HashMap<Integer, Bitmap> mPreviewImages = new HashMap<Integer, 
Bitmap>();
        private boolean mCurrentPreviewImageMissing = false;
 
        private boolean mIsBound = false;
 
+       private int mCurrentSlide = 0;
+
        private CommunicationService mCommunicationService;
 
        final Messenger mMessenger = new Messenger(new MessageHandler());
@@ -141,22 +140,17 @@ public class TestClient extends Activity {
                        case CommunicationService.MSG_SLIDE_CHANGED:
                                int newSlide = aData.getInt("slide_number");
                                mSlideLabel.setText("Slide " + newSlide);
-                               if (mPreviewImages.containsKey(newSlide)) {
-                                       
mImageView.setImageBitmap(mPreviewImages.get(newSlide));
-                                       mCurrentPreviewImageMissing = false;
-                               } else {
-                                       mCurrentPreviewImageMissing = true;
-                               }
-                               break;
+                               mCurrentPreviewImageMissing = true;
+                               // We continue on to try and update the image.
                        case CommunicationService.MSG_SLIDE_PREVIEW:
                                int aSlideNumber = aData.getInt("slide_number");
-                               byte[] aPreviewImage = 
aData.getByteArray("preview_image");
-                               Bitmap aBitmap = 
BitmapFactory.decodeByteArray(aPreviewImage,
-                                               0, aPreviewImage.length);
-                               mPreviewImages.put(aSlideNumber, aBitmap);
-                               if (mCurrentPreviewImageMissing) {
-                                       mImageView.setImageBitmap(aBitmap);
-                                       mCurrentPreviewImageMissing = false;
+                               if ( mCurrentPreviewImageMissing ) {
+                                       Bitmap aImage = mCommunicationService
+                                                       
.getPreviewImage(aSlideNumber);
+                                       if (aImage != null) {
+                                               
mImageView.setImageBitmap(aImage);
+                                               mCurrentPreviewImageMissing = 
false;
+                                       }
                                }
                                break;
 
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
 
b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
index eec69fc..ab2794a 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
@@ -2,6 +2,8 @@ package org.libreoffice.impressremote.communication;
 
 import android.app.Service;
 import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Messenger;
@@ -72,4 +74,9 @@ public class CommunicationService extends Service {
                mClient.closeConnection();
        }
 
+       public Bitmap getPreviewImage(int aSlide) {
+               return mReceiver.getPreviewImage(aSlide);
+       }
+
+
 }
diff --git 
a/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
 
b/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
index 8418cab..05d26e0 100644
--- 
a/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
+++ 
b/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
@@ -10,22 +10,32 @@ package org.libreoffice.impressremote.communication;
 
 import java.util.ArrayList;
 
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.os.Bundle;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
 import android.util.Base64;
+import android.util.SparseArray;
 
 public class Receiver {
 
        private Messenger mActivityMessenger;
 
+       private SparseArray<byte[]> mPreviewImages = new SparseArray<byte[]>();
+
        public void setActivityMessenger(Messenger aActivityMessenger) {
                mActivityMessenger = aActivityMessenger;
        }
 
+       public Bitmap getPreviewImage(int aSlide) {
+               byte[] aImage = mPreviewImages.get(aSlide);
+               return BitmapFactory.decodeByteArray(aImage, 0, aImage.length);
+       }
+
        public void parseCommand(ArrayList<String> aCommand) {
-               System.out.println("parsing " +aCommand.get(0));
+               System.out.println("parsing " + aCommand.get(0));
                if (mActivityMessenger == null) {
                        return;
                }
@@ -46,11 +56,15 @@ public class Receiver {
                        int aSlideNumber = Integer.parseInt(aCommand.get(1));
                        String aImageString = aCommand.get(2);
                        byte[] aImage = Base64.decode(aImageString, 
Base64.DEFAULT);
+
+                       // Store image internally
+                       mPreviewImages.put(aSlideNumber, aImage);
+
+                       // Notify the frontend
                        Message aMessage = Message.obtain(null,
                                        CommunicationService.MSG_SLIDE_PREVIEW);
                        Bundle aData = new Bundle();
                        aData.putInt("slide_number", aSlideNumber);
-                       aData.putByteArray("preview_image", aImage);
                        aMessage.setData(aData);
                        try {
                                mActivityMessenger.send(aMessage);
diff --git a/sd/source/ui/inc/Server.hxx b/sd/source/ui/inc/Server.hxx
index 065b1cd..f3595ad 100644
--- a/sd/source/ui/inc/Server.hxx
+++ b/sd/source/ui/inc/Server.hxx
@@ -43,6 +43,7 @@ namespace sd
             static void setup();
             static void presentationStarted( const css::uno::Reference<
                 css::presentation::XSlideShowController > &rController );
+            static void presentationStopped();
             void informListenerDestroyed();
         private:
             Server();
@@ -54,7 +55,6 @@ namespace sd
             void execute();
             static Transmitter *pTransmitter;
             static rtl::Reference<Listener> mListener;
-            static rtl::Reference<ImagePreparer> mPreparer;
     };
 }
 
diff --git a/sd/source/ui/remotecontrol/Listener.cxx 
b/sd/source/ui/remotecontrol/Listener.cxx
index 9607707..1f55710 100644
--- a/sd/source/ui/remotecontrol/Listener.cxx
+++ b/sd/source/ui/remotecontrol/Listener.cxx
@@ -25,22 +25,31 @@ using rtl::OStringBuffer;
 Listener::Listener( const ::rtl::Reference<Server>& rServer, sd::Transmitter 
*aTransmitter  )
     : ::cppu::WeakComponentImplHelper1< XSlideShowListener >( m_aMutex ),
       mServer( rServer ),
-      pTransmitter( NULL )
+      pTransmitter( NULL ),
+      mPreparer()
 {
     pTransmitter = aTransmitter;
+    fprintf( stderr, "Listener created %p\n", this );
 }
 
 Listener::~Listener()
 {
+    fprintf( stderr, "Listener destroyed %p\n", this );
 }
 
 void Listener::init( const css::uno::Reference< 
css::presentation::XSlideShowController >& aController)
 {
+    fprintf( stderr, "Initing\n" );
     if ( aController.is() )
     {
+        fprintf( stderr, "Is -- now copying refrerence.\n" );
         mController = css::uno::Reference< 
css::presentation::XSlideShowController >( aController );
+        fprintf( stderr, "Registering listener\n" );
         aController->addSlideShowListener( this );
         fprintf( stderr, "Registered listener.\n" );
+
+        mPreparer.set( new ImagePreparer( aController, pTransmitter, mPreparer 
) );
+        mPreparer->launch();
     }
     else
     {
@@ -123,6 +132,13 @@ void SAL_CALL Listener::slideAnimationsEnded (void)
 
 void SAL_CALL Listener::disposing (void)
 {
+    fprintf( stderr, "disposing void\n" );
+    if ( mPreparer.is() )
+    {
+        delete mPreparer.get();
+        mPreparer = NULL;
+    }
+
     pTransmitter = NULL;
     if ( mController.is() )
     {
@@ -136,6 +152,7 @@ void SAL_CALL Listener::disposing (
     const css::lang::EventObject& rEvent)
     throw (::com::sun::star::uno::RuntimeException)
 {
+    fprintf( stderr, "disposing with Events\n" );
     (void) rEvent;
     dispose();
 }
diff --git a/sd/source/ui/remotecontrol/Listener.hxx 
b/sd/source/ui/remotecontrol/Listener.hxx
index 09c04ea..92a0b93 100644
--- a/sd/source/ui/remotecontrol/Listener.hxx
+++ b/sd/source/ui/remotecontrol/Listener.hxx
@@ -21,6 +21,7 @@
 
 #include "Server.hxx"
 #include "Transmitter.hxx"
+#include "ImagePreparer.hxx"
 
 namespace css = ::com::sun::star;
 
@@ -63,6 +64,7 @@ private:
     rtl::Reference<Server> mServer;
     sd::Transmitter *pTransmitter;
     css::uno::Reference< css::presentation::XSlideShowController > mController;
+    rtl::Reference<sd::ImagePreparer> mPreparer;
 };
 }
 #endif // _SD_IMPRESSREMOTE_LISTENER_HXX
diff --git a/sd/source/ui/remotecontrol/Server.cxx 
b/sd/source/ui/remotecontrol/Server.cxx
index ab6a212..0329e27 100644
--- a/sd/source/ui/remotecontrol/Server.cxx
+++ b/sd/source/ui/remotecontrol/Server.cxx
@@ -93,13 +93,10 @@ void Server::listenThread()
         }
     }
     // TODO: deal with transmision errors gracefully.
+    fprintf( stderr, "done with transmitting\n" );
     mListener->disposing();
     mListener = NULL;
 
-    if ( mPreparer.is() )
-        delete mPreparer.get();
-    mPreparer = NULL;
-
     delete pTransmitter;
     pTransmitter = NULL;
     fprintf( stderr, "Finished listening\n" );
@@ -140,18 +137,21 @@ void Server::presentationStarted( const 
css::uno::Reference<
     {
         mListener = rtl::Reference<Listener>( new Listener( spServer, 
pTransmitter ) );
         mListener->init( rController );
-
-        mPreparer = rtl::Reference<ImagePreparer>( new ImagePreparer( 
rController, pTransmitter ) );
-        mPreparer->launch();
     }
 }
 
-
+void Server::presentationStopped()
+{
+    if ( mListener.is() )
+    {
+        mListener->disposing();
+        mListener = NULL;
+    }
+}
 
 Server *sd::Server::spServer = NULL;
 Transmitter *sd::Server::pTransmitter = NULL;
 rtl::Reference<Listener> sd::Server::mListener = NULL;
-rtl::Reference<ImagePreparer> sd::Server::mPreparer = NULL;
 
 void Server::setup()
 {
diff --git a/sd/source/ui/slideshow/slideshow.cxx 
b/sd/source/ui/slideshow/slideshow.cxx
index 05bf461..f8db9aa 100644
--- a/sd/source/ui/slideshow/slideshow.cxx
+++ b/sd/source/ui/slideshow/slideshow.cxx
@@ -58,7 +58,6 @@
 #include "sdattr.hrc"
 #include "FactoryIds.hxx"
 #include "ViewShell.hxx"
-#include "Server.hxx"
 #include "SlideShowRestarter.hxx"
 #include "DrawController.hxx"
 #include <boost/bind.hpp>
@@ -1074,7 +1073,6 @@ void SlideShow::activate( ViewShellBase& rBase )
     if( mxController.is() )
         mxController->activate();
 
-    Server::presentationStarted( mxController.get() );
 }
 
 // ---------------------------------------------------------
diff --git a/sd/source/ui/slideshow/slideshowimpl.cxx 
b/sd/source/ui/slideshow/slideshowimpl.cxx
index da4a646..d560417 100644
--- a/sd/source/ui/slideshow/slideshowimpl.cxx
+++ b/sd/source/ui/slideshow/slideshowimpl.cxx
@@ -82,7 +82,7 @@
 #include "canvas/elapsedtime.hxx"
 #include "avmedia/mediawindow.hxx"
 #include  "svtools/colrdlg.hxx"
-
+#include "Server.hxx"
 #include <boost/noncopyable.hpp>
 #include <boost/bind.hpp>
 
@@ -613,6 +613,7 @@ SlideshowImpl::~SlideshowImpl()
 
 void SAL_CALL SlideshowImpl::disposing()
 {
+    Server::presentationStopped();
     if( mxShow.is() && mpDoc )
         NotifyDocumentEvent( mpDoc, "OnEndPresentation" );
 
@@ -1512,6 +1513,7 @@ void SAL_CALL SlideshowImpl::resume() throw 
(RuntimeException)
                 comphelper::anyToString( cppu::getCaughtException() ),
                 RTL_TEXTENCODING_UTF8 )).getStr() );
     }
+    Server::presentationStarted( this );
 }
 
 // ---------------------------------------------------------
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to