[Libreoffice-commits] .: Branch 'feature/remote' - 2 commits - android/sdremote sd/source

Andrzej J.R. Hunt ajrhunt at kemper.freedesktop.org
Fri Jul 20 12:44:47 PDT 2012


 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 <andrzej at 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 <andrzej at 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 );
 }
 
 // ---------------------------------------------------------


More information about the Libreoffice-commits mailing list