Commit 0530638a authored by Erwan Tulou's avatar Erwan Tulou

skins2: implement art display in image controls

This patch gives skins developpers the possibility to display the art file
 associated to the current input in an image control.

It features the following :
    - a new 'art' boolean parameter is added for the Image control (skin.dtd)
    - when set to true, the skin engine will reuse this control to display
      the current art file
    - in addition to 'scale' and 'mosaic', the resize parameter can now accept
      a new 'scale2' value, that respects the original aspect ratio of art files
parent a8fcb7dd
......@@ -107,6 +107,8 @@ SOURCES_skins2 = \
src/dialogs.hpp \
src/file_bitmap.cpp \
src/file_bitmap.hpp \
src/art_bitmap.cpp \
src/art_bitmap.hpp \
src/ft2_bitmap.cpp \
src/ft2_bitmap.hpp \
src/ft2_font.cpp \
......@@ -178,6 +180,8 @@ SOURCES_skins2 = \
utils/var_percent.hpp \
utils/var_text.cpp \
utils/var_text.hpp \
utils/var_string.cpp \
utils/var_string.hpp \
utils/var_tree.cpp \
utils/var_tree.hpp \
\
......
......@@ -27,26 +27,47 @@
#include "../events/evt_generic.hpp"
#include "../src/os_factory.hpp"
#include "../src/os_graphics.hpp"
#include "../src/vlcproc.hpp"
#include "../src/scaled_bitmap.hpp"
#include "../src/art_bitmap.hpp"
#include "../utils/position.hpp"
CtrlImage::CtrlImage( intf_thread_t *pIntf, const GenericBitmap &rBitmap,
CtrlImage::CtrlImage( intf_thread_t *pIntf, GenericBitmap &rBitmap,
CmdGeneric &rCommand, resize_t resizeMethod,
const UString &rHelp, VarBool *pVisible ):
CtrlFlat( pIntf, rHelp, pVisible ), m_rBitmap( rBitmap ),
m_rCommand( rCommand ), m_resizeMethod( resizeMethod )
const UString &rHelp, VarBool *pVisible, bool art ):
CtrlFlat( pIntf, rHelp, pVisible ),
m_pBitmap( &rBitmap ), m_pOriginalBitmap( &rBitmap ),
m_rCommand( rCommand ), m_resizeMethod( resizeMethod ), m_art( art )
{
// Create an initial unscaled image in the buffer
m_pImage = OSFactory::instance( pIntf )->createOSGraphics(
rBitmap.getWidth(), rBitmap.getHeight() );
m_pImage->drawBitmap( m_rBitmap );
m_pImage->drawBitmap( *m_pBitmap );
// Observe the variable
if( m_art )
{
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
pVlcProc->getStreamArtVar().addObserver( this );
ArtBitmap::initArtBitmap( getIntf() );
}
}
CtrlImage::~CtrlImage()
{
delete m_pImage;
if( m_art )
{
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
pVlcProc->getStreamArtVar().delObserver( this );
ArtBitmap::freeArtBitmap( );
}
}
......@@ -104,7 +125,7 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
{
OSFactory *pOsFactory = OSFactory::instance( getIntf() );
// Rescale the image with the actual size of the control
ScaledBitmap bmp( getIntf(), m_rBitmap, width, height );
ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height );
delete m_pImage;
m_pImage = pOsFactory->createOSGraphics( width, height );
m_pImage->drawBitmap( bmp, 0, 0 );
......@@ -112,7 +133,7 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
}
}
else
else if( m_resizeMethod == kMosaic )
{
// Use mosaic method
while( width > 0 )
......@@ -132,6 +153,68 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
width -= m_pImage->getWidth();
}
}
else if( m_resizeMethod == kScaleAndRatioPreserved )
{
int width = pPos->getWidth();
int height = pPos->getHeight();
int w = m_pBitmap->getWidth();
int h = m_pBitmap->getHeight();
int scaled_height = width * h / w;
int scaled_width = height * w / h;
int x, y;
if( scaled_height > height )
{
width = scaled_width;
x = ( pPos->getWidth() - width ) / 2;
y = 0;
}
else
{
height = scaled_height;
x = 0;
y = ( pPos->getHeight() - height ) / 2;
}
OSFactory *pOsFactory = OSFactory::instance( getIntf() );
// Rescale the image with the actual size of the control
ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height );
delete m_pImage;
m_pImage = pOsFactory->createOSGraphics( width, height );
m_pImage->drawBitmap( bmp, 0, 0 );
rImage.drawGraphics( *m_pImage, 0, 0, xDest + x, yDest + y );
}
}
}
void CtrlImage::onUpdate( Subject<VarString> &rVariable, void* arg )
{
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
if( &rVariable == &pVlcProc->getStreamArtVar() )
{
string str = ((VarString&)rVariable).get();
GenericBitmap* pArt = (GenericBitmap*) ArtBitmap::getArtBitmap( str );
m_pBitmap = pArt ? pArt : m_pOriginalBitmap;
msg_Dbg( getIntf(), "art file %s to be displayed (wxh = %ix%i)",
str.c_str(),
m_pBitmap->getWidth(),
m_pBitmap->getHeight() );
delete m_pImage;
m_pImage = OSFactory::instance( getIntf() )->createOSGraphics(
m_pBitmap->getWidth(),
m_pBitmap->getHeight() );
m_pImage->drawBitmap( *m_pBitmap );
notifyLayout();
}
}
......@@ -26,28 +26,31 @@
#define CTRL_IMAGE_HPP
#include "../commands/cmd_generic.hpp"
#include "../utils/observer.hpp"
#include "ctrl_flat.hpp"
class GenericBitmap;
class OSGraphics;
class CmdGeneric;
class VarString;
/// Control image
class CtrlImage: public CtrlFlat
class CtrlImage: public CtrlFlat, public Observer<VarString>
{
public:
/// Resize methods
enum resize_t
{
kMosaic, // Repeat the base image in a mosaic
kScale // Scale the base image
kMosaic, // Repeat the base image in a mosaic
kScale, // Scale the base image
kScaleAndRatioPreserved // Scale image (aspect ratio preserved)
};
// Create an image with the given bitmap (which is NOT copied)
CtrlImage( intf_thread_t *pIntf, const GenericBitmap &rBitmap,
CtrlImage( intf_thread_t *pIntf, GenericBitmap &rBitmap,
CmdGeneric &rCommand, resize_t resizeMethod,
const UString &rHelp, VarBool *pVisible );
const UString &rHelp, VarBool *pVisible, bool art );
virtual ~CtrlImage();
/// Handle an event on the control
......@@ -64,13 +67,22 @@ public:
private:
/// Bitmap
const GenericBitmap &m_rBitmap;
GenericBitmap* m_pBitmap;
/// original Bitmap
GenericBitmap* m_pOriginalBitmap;
/// Buffer to stored the rendered bitmap
OSGraphics *m_pImage;
/// Command triggered by a double-click on the image
CmdGeneric &m_rCommand;
/// Resize method
resize_t m_resizeMethod;
/// does the image get updated as art
bool m_art;
/// Method called when the observed variable is modified
virtual void onUpdate( Subject<VarString> &rVariable, void* );
};
#endif
......@@ -574,9 +574,12 @@ void Builder::addImage( const BuilderData::Image &rData )
VarBool *pVisible = pInterpreter->getVarBool( rData.m_visible, m_pTheme );
CtrlImage::resize_t resizeMethod =
(rData.m_resize == "scale" ? CtrlImage::kScale : CtrlImage::kMosaic);
rData.m_resize == "scale" ? CtrlImage::kScale :
rData.m_resize == "mosaic" ? CtrlImage::kMosaic :
CtrlImage::kScaleAndRatioPreserved;
CtrlImage *pImage = new CtrlImage( getIntf(), *pBmp, *pCommand,
resizeMethod, UString( getIntf(), rData.m_help.c_str() ), pVisible );
resizeMethod, UString( getIntf(), rData.m_help.c_str() ), pVisible,
rData.m_art );
m_pTheme->m_controls[rData.m_id] = CtrlGenericPtr( pImage );
// Compute the position of the control
......
......@@ -11,7 +11,7 @@ Layout id:string width:int height:int minWidth:int maxWidth:int minHeight:int ma
Anchor xPos:int yPos:int leftTop:string range:int priority:int points:string layoutId:string
Button id:string xPos:int yPos:int leftTop:string rightBottom:string xKeepRatio:bool yKeepRatio:bool visible:string upId:string downId:string overId:string actionId:string tooltip:string help:string layer:int windowId:string layoutId:string panelId:string
Checkbox id:string xPos:int yPos:int leftTop:string rightBottom:string xKeepRatio:bool yKeepRatio:bool visible:string up1Id:string down1Id:string over1Id:string up2Id:string down2Id:string over2Id:string state:string action1:string action2:string tooltip1:string tooltip2:string help:string layer:int windowId:string layoutId:string panelId:string
Image id:string xPos:int yPos:int leftTop:string rightBottom:string xKeepRatio:bool yKeepRatio:bool visible:string bmpId:string actionId:string action2Id:string resize:string help:string layer:int windowId:string layoutId:string panelId:string
Image id:string xPos:int yPos:int leftTop:string rightBottom:string xKeepRatio:bool yKeepRatio:bool visible:string bmpId:string actionId:string action2Id:string resize:string help:string art:bool layer:int windowId:string layoutId:string panelId:string
IniFile id:string file:string
Panel id:string xPos:int yPos:int leftTop:string rightBottom:string xKeepRatio:bool yKeepRatio:bool width:int height:int layer:int windowId:string layoutId:string panelId:string
Text id:string xPos:int yPos:int visible:string fontId:string text:string width:int leftTop:string rightBottom:string xKeepRatio:bool yKeepRatio:bool color:uint32_t scrolling:string alignment:string help:string layer:int windowId:string layoutId:string panelId:string
......
......@@ -267,8 +267,8 @@ m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom(
/// Type definition
struct Image
{
Image( const string & id, int xPos, int yPos, const string & leftTop, const string & rightBottom, bool xKeepRatio, bool yKeepRatio, const string & visible, const string & bmpId, const string & actionId, const string & action2Id, const string & resize, const string & help, int layer, const string & windowId, const string & layoutId, const string & panelId ):
m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_xKeepRatio( xKeepRatio ), m_yKeepRatio( yKeepRatio ), m_visible( visible ), m_bmpId( bmpId ), m_actionId( actionId ), m_action2Id( action2Id ), m_resize( resize ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ), m_panelId( panelId ) {}
Image( const string & id, int xPos, int yPos, const string & leftTop, const string & rightBottom, bool xKeepRatio, bool yKeepRatio, const string & visible, const string & bmpId, const string & actionId, const string & action2Id, const string & resize, const string & help, bool art, int layer, const string & windowId, const string & layoutId, const string & panelId ):
m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_xKeepRatio( xKeepRatio ), m_yKeepRatio( yKeepRatio ), m_visible( visible ), m_bmpId( bmpId ), m_actionId( actionId ), m_action2Id( action2Id ), m_resize( resize ), m_help( help ), m_art( art ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ), m_panelId( panelId ) {}
string m_id;
int m_xPos;
......@@ -283,6 +283,7 @@ m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom(
string m_action2Id;
string m_resize;
string m_help;
bool m_art;
int m_layer;
string m_windowId;
string m_layoutId;
......
......@@ -288,6 +288,7 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
DefaultAttr( attr, "action2", "none" );
DefaultAttr( attr, "resize", "mosaic" );
DefaultAttr( attr, "help", "" );
DefaultAttr( attr, "art", "false" );
const BuilderData::Image imageData( uniqueId( attr["id"] ),
atoi( attr["x"] ) + m_xOffset, atoi( attr["y"] ) + m_yOffset,
......@@ -295,7 +296,8 @@ void SkinParser::handleBeginElement( const string &rName, AttrList_t &attr )
convertBoolean( attr["xkeepratio"] ),
convertBoolean( attr["ykeepratio"] ), attr["visible"],
attr["image"], attr["action"], attr["action2"], attr["resize"],
attr["help"], m_curLayer, m_curWindowId, m_curLayoutId,
attr["help"], convertBoolean( attr["art"] ),
m_curLayer, m_curWindowId, m_curLayoutId,
m_panelStack.back() );
m_curLayer++;
m_pData->m_listImage.push_back( imageData );
......
/*****************************************************************************
* art_bitmap.cpp
*****************************************************************************
* Copyright (C) 2010 the VideoLAN team
* $Id$
*
* Author: Erwan Tulou <erwan10@vidoelan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "art_bitmap.hpp"
#include <vlc_image.h>
// static variables
intf_thread_t* ArtBitmap::m_pIntf = NULL;
image_handler_t* ArtBitmap::m_pImageHandler = NULL;
list<ArtBitmap*> ArtBitmap::m_listBitmap;
ArtBitmap::ArtBitmap( string uriName ):
FileBitmap( m_pIntf, m_pImageHandler, uriName, -1 ), m_uriName( uriName )
{
}
void ArtBitmap::initArtBitmap( intf_thread_t* pIntf )
{
if( m_pIntf )
return;
// retain reference to skins interface
m_pIntf = pIntf;
// initialize handler
m_pImageHandler = image_HandlerCreate( pIntf );
if( !m_pImageHandler )
msg_Err( m_pIntf, "initialization of art bitmaps failed" );
}
ArtBitmap* ArtBitmap::getArtBitmap( string uriName )
{
if( !m_pImageHandler )
return NULL;
// check whether art is already loaded
list<ArtBitmap*>::const_iterator it;
for( it = m_listBitmap.begin(); it != m_listBitmap.end(); ++it )
{
if( (*it)->getUriName() == uriName )
return *it;
}
// create and retain a new ArtBitmap since uri if not yet known
ArtBitmap* pArt = new ArtBitmap( uriName );
if( pArt && pArt->getWidth() && pArt->getHeight() )
{
m_listBitmap.push_back( pArt );
return pArt;
}
else
{
delete pArt;
return NULL;
}
}
void ArtBitmap::freeArtBitmap( )
{
m_pIntf = NULL;
if( m_pImageHandler )
{
image_HandlerDelete( m_pImageHandler );
m_pImageHandler = NULL;
}
m_listBitmap.clear();
}
/*****************************************************************************
* art_bitmap.hpp
*****************************************************************************
* Copyright (C) 2010 the VideoLAN team
* $Id$
*
* Author: Erwan Tulou <erwan10@vidoelan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef ART_BITMAP_HPP
#define ART_BITMAP_HPP
#include "file_bitmap.hpp"
#include <string>
#include <list>
/// Class for art bitmaps
class ArtBitmap: public FileBitmap
{
public:
static ArtBitmap* getArtBitmap( string uriName );
static void initArtBitmap( intf_thread_t* pIntf );
static void freeArtBitmap( );
string getUriName() { return m_uriName; }
protected:
/// Constructor/destructor
ArtBitmap( string uriName );
virtual ~ArtBitmap() {}
/// skins2 interface
static intf_thread_t *m_pIntf;
/// Image handler (used to load art files)
static image_handler_t *m_pImageHandler;
// keep a cache of art already open
static list<ArtBitmap*> m_listBitmap;
private:
// uriName
string m_uriName;
};
#endif
......@@ -50,6 +50,7 @@
#include "../commands/cmd_audio.hpp"
#include "../commands/cmd_callbacks.hpp"
#include "../utils/var_bool.hpp"
#include "../utils/var_string.hpp"
#include <sstream>
#include <assert.h>
......@@ -129,6 +130,8 @@ VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ),
pVarManager->registerVar( m_cVarStreamBitRate, "bitrate" );
m_cVarStreamSampleRate = VariablePtr( new VarText( getIntf(), false ) );
pVarManager->registerVar( m_cVarStreamSampleRate, "samplerate" );
m_cVarStreamArt = VariablePtr( new VarString( getIntf() ) );
pVarManager->registerVar( m_cVarStreamArt, "streamArt" );
// Register the equalizer bands
for( int i = 0; i < EqualizerBands::kNbBands; i++)
......@@ -430,6 +433,7 @@ int VlcProc::onGenericCallback( vlc_object_t *pObj, const char *pVariable,
#define SET_BOOL(m,v) ((VarBoolImpl*)(m).get())->set(v)
#define SET_STREAMTIME(m,v,b) ((StreamTime*)(m).get())->set(v,b)
#define SET_TEXT(m,v) ((VarText*)(m).get())->set(v)
#define SET_STRING(m,v) ((VarString*)(m).get())->set(v)
#define SET_VOLUME(m,v,b) ((Volume*)(m).get())->set(v,b)
void VlcProc::on_item_current_changed( vlc_object_t* p_obj, vlc_value_t newVal )
......@@ -446,6 +450,11 @@ void VlcProc::on_item_current_changed( vlc_object_t* p_obj, vlc_value_t newVal )
SET_TEXT( m_cVarStreamURI, UString( getIntf(), psz_uri ) );
free( psz_uri );
// Update art uri
char *psz_art = input_item_GetArtURL( p_item );
SET_STRING( m_cVarStreamArt, string( psz_art ? psz_art : "" ) );
free( psz_art );
// Update playtree
getPlaytreeVar().onUpdateCurrent( true );
}
......@@ -767,4 +776,5 @@ void VlcProc::setFullscreenVar( bool b_fullscreen )
#undef SET_BOOL
#undef SET_STREAMTIME
#undef SET_TEXT
#undef SET_STRING
#undef SET_VOLUME
......@@ -36,6 +36,7 @@
#include "../vars/volume.hpp"
#include "../utils/position.hpp"
#include "../utils/var_text.hpp"
#include "../utils/var_string.hpp"
#include "../commands/cmd_generic.hpp"
#include "../controls/ctrl_video.hpp"
......@@ -81,6 +82,10 @@ public:
VarText &getStreamSampleRateVar()
{ return *((VarText*)(m_cVarStreamSampleRate.get())); }
/// Getter for the stream Art url variable
VarString &getStreamArtVar()
{ return *((VarString*)(m_cVarStreamArt.get())); }
/// Getter/Setter for the fullscreen variable
VarBool &getFullscreenVar() { return *((VarBool*)(m_cVarFullscreen.get())); }
void setFullscreenVar( bool );
......@@ -128,6 +133,7 @@ private:
VariablePtr m_cVarStreamURI;
VariablePtr m_cVarStreamBitRate;
VariablePtr m_cVarStreamSampleRate;
VariablePtr m_cVarStreamArt;
/// Variable for the "mute" state
VariablePtr m_cVarMute;
/// Variables related to the input
......
/*****************************************************************************
* var_string.cpp
*****************************************************************************
* Copyright (C) 2010 the VideoLAN team
* $Id$
*
* Author: Erwan Tulou <erwan10 aT videolan DoT org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "var_string.hpp"
const string VarString::m_type = "string";
void VarString::set( string str )
{
// If the value has changed, notify the observers
if( m_value != str )
{
m_value = str;
notify( NULL );
}
}
/*****************************************************************************
* var_string.hpp
*****************************************************************************
* Copyright (C) 2010 the VideoLAN team
* $Id$
*
* Author: Erwan Tulou <erwan10 aT videolan DoT org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VAR_STRING
#define VAR_STRING
#include "variable.hpp"
#include "observer.hpp"
class VarString;
/// String variable
class VarString: public Variable, public Subject<VarString>
{
public:
VarString( intf_thread_t *pIntf ): Variable( pIntf ), m_value( string("tit") ) { }
virtual ~VarString() { }
/// Get the variable type
virtual const string &getType() const { return m_type; }
/// Set the internal value
virtual void set( string str );
virtual string get() const { return m_value; }
private:
/// Variable type
static const string m_type;
/// string value
string m_value;
};
#endif
......@@ -140,6 +140,7 @@
action2 CDATA "none"
resize CDATA "mosaic"
help CDATA ""
art CDATA "false"
>
<!ELEMENT Button EMPTY>
<!ATTLIST Button
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment