/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <iomanip>
+#include <fstream>
#include <dali/public-api/images/native-image.h>
#include <dali/public-api/events/touch-event.h>
#include <dali/public-api/events/touch-point.h>
#include <dali/public-api/common/stage.h>
-#include <dali/public-api/actors/blending.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
#include <dali/public-api/images/buffer-image.h>
+#include <dali/public-api/images/pixel.h>
#include <dali/integration-api/debug.h>
}
};
+#ifdef ENABLE_INDICATOR_IMAGE_SAVING
+
+void SaveIndicatorImage( Dali::NativeImageSourcePtr nativeImageSource )
+{
+ // Save image data to disk in BMP form.
+ static int gFilenameCounter = 0;
+ static const char bmpHeader[] = {
+ 0x42, 0x4d, 0x0a, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x7c, 0x00,
+ 0x00, 0x00,
+ 0xe0, 0x01, 0x00, 0x00, // Width (480)
+ 0x1b, 0x00, 0x00, 0x00, // Height ( 27)
+ 0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
+ 0x00, 0x00, 0x80, 0xca, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ // This is a BMP header with width & height hard-coded in.
+ // The data was first determined by dumping the raw data and inspecting in GIMP, before creating this header data.
+ std::vector<unsigned char> buffer;
+ unsigned int w = 0;
+ unsigned int h = 0;
+ Dali::Pixel::Format pixelFormat;
+ if( nativeImageSource->GetPixels( buffer, w, h, pixelFormat ) )
+ {
+ int imageSize = w * h * 4;
+ std::stringstream fileName;
+ // Give each file an incremental filename.
+ fileName << "/opt/usr/media/Images/out-" << std::setfill( '0' ) << std::setw( 5 ) << gFilenameCounter << ".bmp";
+
+ std::ofstream outfile( fileName.str().c_str(), std::ofstream::binary );
+ if( outfile.is_open() )
+ {
+ DALI_LOG_WARNING( "Saving Indicator Image w:%d, h:%d, %s\n", w, h, fileName.str().c_str() );
+
+ outfile.write( bmpHeader, sizeof( bmpHeader ) / sizeof( bmpHeader[0] ) ); // Size of the BMP header.
+ outfile.write( (const char*)buffer.data(), imageSize );
+ outfile.close();
+ gFilenameCounter++;
+ }
+ else
+ {
+ DALI_LOG_ERROR( "COULD NOT OPEN FOR SAVING: %s\n", fileName.str().c_str() );
+ }
+ }
+}
+
+#endif
+
} // anonymous namespace
: mIndicator(indicator),
mEcoreEventHandler(NULL)
{
-#ifdef WAYLAND
+#if defined(DALI_PROFILE_MOBILE)
+#if defined(WAYLAND)
mEcoreEventHandler = ecore_event_handler_add(ECORE_WL_EVENT_INDICATOR_FLICK, EcoreEventIndicator, this);
-#elif !defined(DALI_PROFILE_UBUNTU)
+#else
mEcoreEventHandler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, EcoreEventClientMessage, this);
#endif
+#endif // WAYLAND && DALI_PROFILE_MOBILE
}
/**
}
}
}
-
-#ifdef WAYLAND
+#if defined(DALI_PROFILE_MOBILE)
+#if defined(WAYLAND)
/**
* Called when the Ecore indicator event is received.
*/
SetIndicatorVisibility( data, INDICATOR_STAY_WITH_DURATION );
return ECORE_CALLBACK_PASS_ON;
}
-#elif !defined(DALI_PROFILE_UBUNTU)
+#else
/**
* Called when the client messages (i.e. quick panel state) are received.
*/
}
return ECORE_CALLBACK_PASS_ON;
}
-
-#endif // WAYLAND
+#endif
+#endif // WAYLAND && DALI_PROFILE_MOBILE
// Data
Indicator* mIndicator;
bool locked = false;
if( mFileDescriptor > 0 )
{
- if( lockf( mFileDescriptor, F_LOCK, 0 ) == 0 ) // Note, operation may block.
+ struct flock filelock;
+
+ filelock.l_type = F_RDLCK;
+ filelock.l_whence = SEEK_SET;
+ filelock.l_start = 0;
+ filelock.l_len = 0;
+ if( fcntl( mFileDescriptor, F_SETLKW, &filelock ) == -1 )
{
- locked = true;
+ mErrorThrown = true;
+ DALI_LOG_ERROR( "### Failed to lock with fd : %s ###\n", mFilename.c_str() );
}
else
{
- if( errno == EBADF )
- {
- // file descriptor is no longer valid or not writable
- mFileDescriptor = 0;
- mErrorThrown = true;
- DALI_LOG_ERROR( "### Cannot lock indicator: bad file descriptor for %s ###\n", mFilename.c_str() );
- }
+ locked = true;
}
}
+ else
+ {
+ mErrorThrown = true;
+ DALI_LOG_ERROR( "### Invalid fd ###\n" );
+ }
return locked;
}
void Indicator::LockFile::Unlock()
{
DALI_LOG_TRACE_METHOD( gIndicatorLogFilter );
- if( lockf( mFileDescriptor, F_ULOCK, 0 ) != 0 )
+
+ struct flock filelock;
+
+ filelock.l_type = F_UNLCK;
+ filelock.l_whence = SEEK_SET;
+ filelock.l_start = 0;
+ filelock.l_len = 0;
+ if (fcntl(mFileDescriptor, F_SETLKW, &filelock) == -1)
{
- if( errno == EBADF )
- {
- // file descriptor is no longer valid or not writable
- mFileDescriptor = 0;
- mErrorThrown = true;
- DALI_LOG_ERROR( "### Cannot unlock indicator: bad file descriptor for %s\n", mFilename.c_str() );
- }
+ mErrorThrown = true;
+ DALI_LOG_ERROR( "### Failed to lock with fd : %s ###\n", mFilename.c_str() );
}
}
Indicator::Indicator( Adaptor* adaptor, Dali::Window::WindowOrientation orientation, IndicatorInterface::Observer* observer )
: mPixmap( 0 ),
+ mGestureDeltaY( 0.0f ),
mGestureDetected( false ),
mConnection( this ),
mOpacityMode( Dali::Window::OPAQUE ),
mCurrentSharedFile( 0 ),
mSharedBufferType( BUFFER_TYPE_SHM ),
mImpl( NULL ),
- mBackgroundVisible( false )
+ mBackgroundVisible( false ),
+ mTopMargin( 0 )
{
mIndicatorContentActor = Dali::Actor::New();
mIndicatorContentActor.SetParentOrigin( ParentOrigin::TOP_CENTER );
mIndicatorContentActor.RemoveRenderer( mBackgroundRenderer );
mBackgroundVisible = false;
}
+ UpdateTopMargin();
}
void Indicator::SetVisible( Dali::Window::IndicatorVisibleMode visibleMode, bool forceUpdate )
}
mVisible = visibleMode;
+ UpdateTopMargin();
if( mForegroundRenderer && mForegroundRenderer.GetTextures().GetTexture( 0u ) )
{
mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
mIndicatorActor.SetSize( mImageWidth, mImageHeight );
mEventActor.SetSize(mImageWidth, mImageHeight);
+ UpdateTopMargin();
}
}
}
}
+void Indicator::UpdateTopMargin()
+{
+ int newMargin = (mVisible == Dali::Window::VISIBLE && mOpacityMode == Dali::Window::OPAQUE) ? mImageHeight : 0;
+ if (mTopMargin != newMargin)
+ {
+ mTopMargin = newMargin;
+ mAdaptor->IndicatorSizeChanged( mTopMargin );
+ }
+}
+
void Indicator::UpdateVisibility()
{
if( CheckVisibleState() )
else if( scopedLock.IsLocked() )
{
unsigned char *src = mSharedFileInfo[bufferNumber].mSharedFile->GetAddress();
- size_t size = mSharedFileInfo[bufferNumber].mImageWidth * mSharedFileInfo[bufferNumber].mImageHeight * 4;
+ size_t size = static_cast< size_t >( mSharedFileInfo[bufferNumber].mImageWidth ) * mSharedFileInfo[bufferNumber].mImageHeight * 4;
if( mIndicatorBuffer->UpdatePixels( src, size ) )
{
DALI_LOG_TRACE_METHOD_FMT( gIndicatorLogFilter, "W:%d H:%d", mImageWidth, mImageHeight );
Dali::NativeImageSourcePtr nativeImageSource = Dali::NativeImageSource::New( mPixmap );
+#ifdef ENABLE_INDICATOR_IMAGE_SAVING
+ SaveIndicatorImage( nativeImageSource );
+#endif
+
if( nativeImageSource )
{
Dali::Texture texture = Dali::Texture::New( *nativeImageSource );
mIndicatorContentActor.SetSize( mImageWidth, mImageHeight );
mIndicatorActor.SetSize( mImageWidth, mImageHeight );
mEventActor.SetSize( mImageWidth, mImageHeight );
+ UpdateTopMargin();
}
else
{
DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE\n" );
if( mIsShowing )
{
- //mAdaptor->RequestUpdateOnce();
+ mAdaptor->RequestUpdateOnce();
}
break;
}
{
DALI_LOG_INFO( gIndicatorLogFilter, Debug::General, "Indicator client received: OP_UPDATE_DONE [%d]\n", epcEvent->response );
// epcEvent->response == display buffer #
- //UpdateImageData( epcEvent->response );
+ UpdateImageData( epcEvent->response );
break;
}
case OP_SHM_REF0:
void Indicator::OnPan( Dali::Actor actor, const Dali::PanGesture& gesture )
{
- return ;
-
- if( mServerConnection )
- {
- switch( gesture.state )
- {
- case Gesture::Started:
- {
- mGestureDetected = false;
-
- // The gesture position is the current position after it has moved by the displacement.
- // We want to reference the original position.
- mGestureDeltaY = gesture.position.y - gesture.displacement.y;
- }
-
- // No break, Fall through
- case Gesture::Continuing:
- {
- if( mVisible == Dali::Window::AUTO && !mIsShowing )
- {
- // Only take one touch point
- if( gesture.numberOfTouches == 1 && mGestureDetected == false )
- {
- mGestureDeltaY += gesture.displacement.y;
-
- if( mGestureDeltaY >= mImageHeight * SHOWING_DISTANCE_HEIGHT_RATE )
- {
- ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
- mGestureDetected = true;
- }
- }
- }
-
- break;
- }
-
- case Gesture::Finished:
- case Gesture::Cancelled:
- {
- // if indicator is showing, hide again when touching is finished (Since touch leave is activated, checking it in gesture::finish instead of touch::up)
- if( mVisible == Dali::Window::AUTO && mIsShowing )
- {
- ShowIndicator( AUTO_INDICATOR_STAY_DURATION );
- }
- break;
- }
-
-
- default:
- break;
- }
- }
+ // Nothing to do, but we still want to consume pan
}
void Indicator::OnStageTouched(const Dali::TouchEvent& touchEvent)