Commit b2b21b95 authored by Cyril Deguet's avatar Cyril Deguet
Browse files

- all: the text variable "$N" is now the media name, not just a truncated URI

- vlcproc.cpp: update $N and $F variables on an item/playlist change
_ async_queue.cpp: fixed a deadlock between the VLC playlist and the command
  queue
parent c18c56d3
......@@ -154,8 +154,6 @@ SOURCES_skins2 = \
\
vars/playlist.cpp \
vars/playlist.hpp \
vars/stream.cpp \
vars/stream.hpp \
vars/time.cpp \
vars/time.hpp \
vars/volume.cpp \
......
......@@ -103,18 +103,29 @@ void AsyncQueue::remove( const string &rType )
void AsyncQueue::flush()
{
vlc_mutex_lock( &m_lock );
while( m_cmdList.size() > 0 )
while (true)
{
// Pop the first command from the queue
CmdGenericPtr cCommand = m_cmdList.front();
m_cmdList.pop_front();
// And execute it
cCommand.get()->execute();
}
vlc_mutex_lock( &m_lock );
vlc_mutex_unlock( &m_lock );
if( m_cmdList.size() > 0 )
{
// Pop the first command from the queue
CmdGenericPtr cCommand = m_cmdList.front();
m_cmdList.pop_front();
// Unlock the mutex to avoid deadlocks if another thread wants to
// enqueue/remove a command while this one is processed
vlc_mutex_unlock( &m_lock );
// Execute the command
cCommand.get()->execute();
}
else
{
vlc_mutex_unlock( &m_lock );
break;
}
}
}
......
......@@ -23,7 +23,7 @@
#include "cmd_vars.hpp"
#include "../src/vlcproc.hpp"
#include "../vars/stream.hpp"
#include "../utils/var_text.hpp"
#include "../vars/playlist.hpp"
......@@ -35,9 +35,9 @@ void CmdNotifyPlaylist::execute()
}
void CmdSetStream::execute()
void CmdSetText::execute()
{
// Change the stream variable
m_rStream.set( m_name, m_updateVLC );
// Change the text variable
m_rText.set( m_value );
}
......@@ -27,34 +27,32 @@
#include "cmd_generic.hpp"
#include "../utils/ustring.hpp"
class Stream;
class VarText;
/// Command to notify the playlist of a change
DEFINE_COMMAND( NotifyPlaylist, "notify playlist" )
/// Command to set a stream variable
class CmdSetStream: public CmdGeneric
/// Command to set a text variable
class CmdSetText: public CmdGeneric
{
public:
CmdSetStream( intf_thread_t *pIntf, Stream &rStream,
const UString &rName, bool updateVLC ):
CmdGeneric( pIntf ), m_rStream( rStream ), m_name( rName ),
m_updateVLC( updateVLC ) {}
virtual ~CmdSetStream() {}
CmdSetText( intf_thread_t *pIntf, VarText &rText,
const UString &rValue ):
CmdGeneric( pIntf ), m_rText( rText ), m_value( rValue ) {}
virtual ~CmdSetText() {}
/// This method does the real job of the command
virtual void execute();
/// Return the type of the command
virtual string getType() const { return "set stream"; }
virtual string getType() const { return "set text"; }
private:
/// Stream variable to set
Stream &m_rStream;
/// Text variable to set
VarText &m_rText;
/// Value to set
const UString m_name;
bool m_updateVLC;
const UString m_value;
};
......
......@@ -26,7 +26,7 @@
VarManager::VarManager( intf_thread_t *pIntf ): SkinObject( pIntf ),
m_tooltipText( pIntf ), m_helpText( pIntf )
m_tooltipText( pIntf ), m_helpText( pIntf, false )
{
}
......
......@@ -82,13 +82,16 @@ VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ),
REGISTER_VAR( m_cVarRepeat, VarBoolImpl, "playlist.isRepeat" )
REGISTER_VAR( m_cVarTime, StreamTime, "time" )
REGISTER_VAR( m_cVarVolume, Volume, "volume" )
REGISTER_VAR( m_cVarStream, Stream, "stream" )
REGISTER_VAR( m_cVarMute, VarBoolImpl, "vlc.isMute" )
REGISTER_VAR( m_cVarPlaying, VarBoolImpl, "vlc.isPlaying" )
REGISTER_VAR( m_cVarStopped, VarBoolImpl, "vlc.isStopped" )
REGISTER_VAR( m_cVarPaused, VarBoolImpl, "vlc.isPaused" )
REGISTER_VAR( m_cVarSeekable, VarBoolImpl, "vlc.isSeekable" )
#undef REGISTER_VAR
m_cVarStreamName = VariablePtr( new VarText( getIntf(), false ) );
pVarManager->registerVar( m_cVarStreamName, "streamName" );
m_cVarStreamURI = VariablePtr( new VarText( getIntf(), false ) );
pVarManager->registerVar( m_cVarStreamURI, "streamURI" );
// XXX WARNING XXX
// The object variable callbacks are called from other VLC threads,
......@@ -211,7 +214,8 @@ void VlcProc::manage()
pTime->set( pos.f_float, false );
// Get the status of the playlist
playlist_status_t status = getIntf()->p_sys->p_playlist->status.i_status;
playlist_status_t status =
getIntf()->p_sys->p_playlist->status.i_status;
pVarPlaying->set( status == PLAYLIST_RUNNING );
pVarStopped->set( status == PLAYLIST_STOPPED );
......@@ -256,6 +260,10 @@ int VlcProc::onIntfChange( vlc_object_t *pObj, const char *pVariable,
{
VlcProc *pThis = (VlcProc*)pParam;
// Update the stream variable
playlist_t *p_playlist = (playlist_t*)pObj;
pThis->updateStreamName(p_playlist);
// Create a playlist notify command
CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
......@@ -277,9 +285,8 @@ int VlcProc::onIntfShow( vlc_object_t *pObj, const char *pVariable,
VlcProc *pThis = (VlcProc*)pParam;
// Create a raise all command
CmdRaiseAll *pCmd =
new CmdRaiseAll( pThis->getIntf(),
pThis->getIntf()->p_sys->p_theme->getWindowManager() );
CmdRaiseAll *pCmd = new CmdRaiseAll( pThis->getIntf(),
pThis->getIntf()->p_sys->p_theme->getWindowManager() );
// Push the command in the asynchronous command queue
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
......@@ -297,6 +304,10 @@ int VlcProc::onItemChange( vlc_object_t *pObj, const char *pVariable,
{
VlcProc *pThis = (VlcProc*)pParam;
// Update the stream variable
playlist_t *p_playlist = (playlist_t*)pObj;
pThis->updateStreamName(p_playlist);
// Create a playlist notify command
// TODO: selective update
CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
......@@ -318,22 +329,9 @@ int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
// Update the stream variable
playlist_t *p_playlist = (playlist_t*)pObj;
if( p_playlist->p_input )
{
// Create a command to update the stream variable
// XXX: we should not need to access p_input->psz_source directly, a
// getter should be provided by VLC core
Stream *pStream = (Stream*)pThis->m_cVarStream.get();
#warning "FIXME!"
UString srcName( pThis->getIntf(),
p_playlist->p_input->input.p_item->psz_uri );
CmdSetStream *pCmd = new CmdSetStream( pThis->getIntf(), *pStream,
srcName, false );
// Push the command in the asynchronous command queue
pQueue->remove( "set stream" );
pQueue->push( CmdGenericPtr( pCmd ) );
}
pThis->updateStreamName(p_playlist);
// Create a playlist notify command
// TODO: selective update
......@@ -366,6 +364,39 @@ int VlcProc::onSkinToLoad( vlc_object_t *pObj, const char *pVariable,
}
void VlcProc::updateStreamName( playlist_t *p_playlist )
{
if( p_playlist->p_input )
{
VarText &rStreamName = getStreamNameVar();
VarText &rStreamURI = getStreamURIVar();
// XXX: we should not need to access p_input->psz_source directly, a
// getter should be provided by VLC core
#warning "FIXME!"
string name = p_playlist->p_input->input.p_item->psz_name;
// XXX: This should be done in VLC core, not here...
// Remove path information if any
OSFactory *pFactory = OSFactory::instance( getIntf() );
string::size_type pos = name.rfind( pFactory->getDirSeparator() );
if( pos != string::npos )
{
name = name.substr( pos + 1, name.size() - pos + 1 );
}
UString srcName( getIntf(), name.c_str() );
UString srcURI( getIntf(),
p_playlist->p_input->input.p_item->psz_uri );
// Create commands to update the stream variables
CmdSetText *pCmd1 = new CmdSetText( getIntf(), rStreamName, srcName );
CmdSetText *pCmd2 = new CmdSetText( getIntf(), rStreamURI, srcURI );
// Push the commands in the asynchronous command queue
AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
pQueue->push( CmdGenericPtr( pCmd1 ) );
pQueue->push( CmdGenericPtr( pCmd2 ) );
}
}
void *VlcProc::getWindow( intf_thread_t *pIntf, vout_thread_t *pVout,
int *pXHint, int *pYHint,
unsigned int *pWidthHint,
......
......@@ -28,7 +28,7 @@
#include "../vars/playlist.hpp"
#include "../vars/time.hpp"
#include "../vars/volume.hpp"
#include "../vars/stream.hpp"
#include "../utils/var_text.hpp"
class OSTimer;
class VarBool;
......@@ -54,8 +54,13 @@ class VlcProc: public SkinObject
/// Getter for the volume variable
Volume &getVolumeVar() { return *((Volume*)(m_cVarVolume.get())); }
/// Getter for the stream variable
Stream &getStreamVar() { return *((Stream*)(m_cVarStream.get())); }
/// Getter for the stream name variable
VarText &getStreamNameVar()
{ return *((VarText*)(m_cVarStreamName.get())); }
/// Getter for the stream URI variable
VarText &getStreamURIVar()
{ return *((VarText*)(m_cVarStreamURI.get())); }
/// Set the vout window handle
void setVoutWindow( void *pVoutWindow );
......@@ -77,8 +82,9 @@ class VlcProc: public SkinObject
VariablePtr m_cVarTime;
/// Variable for audio volume
VariablePtr m_cVarVolume;
/// Variable for current stream properties (only name, currently)
VariablePtr m_cVarStream;
/// Variable for current stream properties
VariablePtr m_cVarStreamName;
VariablePtr m_cVarStreamURI;
/// Variable for the "mute" state
VariablePtr m_cVarMute;
/// Variables related to the input
......@@ -98,6 +104,9 @@ class VlcProc: public SkinObject
/// the internal status changes
void manage();
/// Update the stream name variable
void updateStreamName( playlist_t *p_playlist );
/// This function directly calls manage(), because it's boring to
/// always write "pThis->"
static void doManage( SkinObject *pObj );
......
......@@ -27,32 +27,41 @@
#include "../src/var_manager.hpp"
#include "../vars/time.hpp"
#include "../vars/volume.hpp"
#include "../vars/stream.hpp"
const string VarText::m_type = "text";
VarText::VarText( intf_thread_t *pIntf ): Variable( pIntf ),
m_text( pIntf, "" ), m_lastText( pIntf, "" )
VarText::VarText( intf_thread_t *pIntf, bool substVars ): Variable( pIntf ),
m_text( pIntf, "" ), m_lastText( pIntf, "" ), m_substVars( substVars )
{
}
VarText::~VarText()
{
// Remove the observers
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
pVlcProc->getTimeVar().delObserver( this );
pVlcProc->getVolumeVar().delObserver( this );
pVlcProc->getStreamVar().delObserver( this );
VarManager *pVarManager = VarManager::instance( getIntf() );
pVarManager->getHelpText().delObserver( this );
if( m_substVars )
{
// Remove the observers
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
pVlcProc->getTimeVar().delObserver( this );
pVlcProc->getVolumeVar().delObserver( this );
pVlcProc->getStreamURIVar().delObserver( this );
pVlcProc->getStreamNameVar().delObserver( this );
VarManager *pVarManager = VarManager::instance( getIntf() );
pVarManager->getHelpText().delObserver( this );
}
}
const UString VarText::get() const
{
if( !m_substVars )
{
// Do not substitute "$X" variables
return m_text;
}
uint32_t pos;
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
......@@ -67,8 +76,7 @@ const UString VarText::get() const
if( (pos = temp.find( "$H" )) != UString::npos )
{
VarManager *pVarManager = VarManager::instance( getIntf() );
// We use .getRaw() to avoid replacing the $H recursively!
temp.replace( pos, 2, pVarManager->getHelpText().getRaw() );
temp.replace( pos, 2, pVarManager->getHelpText().get() );
}
while( (pos = temp.find( "$T" )) != UString::npos )
{
......@@ -92,13 +100,11 @@ const UString VarText::get() const
}
while( (pos = temp.find( "$N" )) != UString::npos )
{
temp.replace( pos, 2,
pVlcProc->getStreamVar().getAsStringName().c_str() );
temp.replace( pos, 2, pVlcProc->getStreamNameVar().get() );
}
while( (pos = temp.find( "$F" )) != UString::npos )
{
temp.replace( pos, 2,
pVlcProc->getStreamVar().getAsStringFullName().c_str() );
temp.replace( pos, 2, pVlcProc->getStreamURIVar().get() );
}
return temp;
......@@ -113,44 +119,48 @@ void VarText::set( const UString &rText )
return;
}
// Stop observing other variables
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
pVlcProc->getTimeVar().delObserver( this );
pVlcProc->getVolumeVar().delObserver( this );
pVlcProc->getStreamVar().delObserver( this );
VarManager *pVarManager = VarManager::instance( getIntf() );
pVarManager->getHelpText().delObserver( this );
m_text = rText;
// Observe needed variables
if( m_text.find( "$H" ) != UString::npos )
{
pVarManager->getHelpText().addObserver( this );
}
if( m_text.find( "$T" ) != UString::npos )
if( m_substVars )
{
pVlcProc->getTimeVar().addObserver( this );
}
if( m_text.find( "$L" ) != UString::npos )
{
pVlcProc->getTimeVar().addObserver( this );
}
if( m_text.find( "$D" ) != UString::npos )
{
pVlcProc->getTimeVar().addObserver( this );
}
if( m_text.find( "$V" ) != UString::npos )
{
pVlcProc->getVolumeVar().addObserver( this );
}
if( m_text.find( "$N" ) != UString::npos )
{
pVlcProc->getStreamVar().addObserver( this );
}
if( m_text.find( "$F" ) != UString::npos )
{
pVlcProc->getStreamVar().addObserver( this );
// Stop observing other variables
VlcProc *pVlcProc = VlcProc::instance( getIntf() );
pVlcProc->getTimeVar().delObserver( this );
pVlcProc->getVolumeVar().delObserver( this );
pVlcProc->getStreamNameVar().delObserver( this );
pVlcProc->getStreamURIVar().delObserver( this );
VarManager *pVarManager = VarManager::instance( getIntf() );
pVarManager->getHelpText().delObserver( this );
// Observe needed variables
if( m_text.find( "$H" ) != UString::npos )
{
pVarManager->getHelpText().addObserver( this );
}
if( m_text.find( "$T" ) != UString::npos )
{
pVlcProc->getTimeVar().addObserver( this );
}
if( m_text.find( "$L" ) != UString::npos )
{
pVlcProc->getTimeVar().addObserver( this );
}
if( m_text.find( "$D" ) != UString::npos )
{
pVlcProc->getTimeVar().addObserver( this );
}
if( m_text.find( "$V" ) != UString::npos )
{
pVlcProc->getVolumeVar().addObserver( this );
}
if( m_text.find( "$N" ) != UString::npos )
{
pVlcProc->getStreamNameVar().addObserver( this );
}
if( m_text.find( "$F" ) != UString::npos )
{
pVlcProc->getStreamURIVar().addObserver( this );
}
}
notify();
......
......@@ -2,7 +2,7 @@
* var_text.hpp
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: var_text.hpp,v 1.2 2004/01/11 17:12:17 asmax Exp $
* $Id$
*
* Authors: Cyril Deguet <asmax@via.ecp.fr>
* Olivier Teulire <ipkiss@via.ecp.fr>
......@@ -36,7 +36,8 @@ class VarText: public Variable, public Subject<VarText>,
public Observer<VarPercent>, public Observer< VarText >
{
public:
VarText( intf_thread_t *pIntf );
// Set substVars to true to replace "$X" variables in the text
VarText( intf_thread_t *pIntf, bool substVars = true );
virtual ~VarText();
/// Get the variable type
......@@ -57,9 +58,8 @@ class VarText: public Variable, public Subject<VarText>,
UString m_text;
/// Actual text after having replaced the variables
UString m_lastText;
/// Get the raw text without replacing the $something's
const UString &getRaw() const { return m_text; }
/// Flag to activate or not "$X" variables substitution
bool m_substVars;
};
#endif
/*****************************************************************************
* time.cpp
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id$
*
* Authors: Olivier Teulière <ipkiss@via.ecp.fr>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <stdio.h> // snprintf
#include "stream.hpp"
#include "../utils/ustring.hpp"
#include "../src/os_factory.hpp"
#include <vlc/input.h>
void Stream::set( const UString &name, bool updateVLC )
{
VarText::set( name );
// Avoid looping forever...
if( updateVLC )
{
// We have nothing to do here, until we decide that the user
// can change a stream name on the fly...
}
}
const string Stream::getAsStringName() const
{
string fullName = getAsStringFullName();
// XXX: This should be done in VLC core, not here...
// Remove path information if any
OSFactory *pFactory = OSFactory::instance( getIntf() );
string::size_type pos = fullName.rfind( pFactory->getDirSeparator() );
if( pos != string::npos )
{
fullName = fullName.substr( pos + 1, fullName.size() - pos + 1 );
}
return fullName;
}
const string Stream::getAsStringFullName() const
{
string ret;
// XXX: we are not using geIntf()->p_sys->p_input direclty here, because it
// is not updated by VlcProc yet. Anyway, we shouldn't need to do that,
// because VLC core should provide getter functions for the stream name...
if( getIntf()->p_sys->p_playlist->p_input == NULL )
{
ret = "";
}
else
{
#warning "FIXME!"
ret = getIntf()->p_sys->p_playlist->p_input->input.p_item->psz_uri;
}
return ret;
}
/*****************************************************************************
* stream.hpp
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: time.hpp 6996 2004-03-07 12:55:32Z ipkiss $
*
* Authors: Olivier Teulière <ipkiss@via.ecp.fr>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef STREAM_HPP
#define STREAM_HPP
#include "../utils/var_text.hpp"
#include <string>
class UString;</