393 lines
10 KiB
C++
393 lines
10 KiB
C++
/**
|
|
* @file llviewerparcelmedia.cpp
|
|
* @brief Handlers for multimedia on a per-parcel basis
|
|
*
|
|
* $LicenseInfo:firstyear=2007&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2007-2008, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlife.com/developers/opensource/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at http://secondlife.com/developers/opensource/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
#include "llviewerparcelmedia.h"
|
|
|
|
#include "llagent.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llviewermedia.h"
|
|
#include "llviewerregion.h"
|
|
#include "llparcel.h"
|
|
#include "llviewerparcelmgr.h"
|
|
#include "lluuid.h"
|
|
#include "message.h"
|
|
#include "llviewerparcelmediaautoplay.h"
|
|
#include "llviewerwindow.h"
|
|
#include "llfirstuse.h"
|
|
|
|
// Static Variables
|
|
|
|
S32 LLViewerParcelMedia::sMediaParcelLocalID = 0;
|
|
LLUUID LLViewerParcelMedia::sMediaRegionID;
|
|
|
|
// Local functions
|
|
void callback_play_media(S32 option, void* data);
|
|
|
|
// Move this to its own file.
|
|
// helper class that tries to download a URL from a web site and calls a method
|
|
// on the Panel Land Media and to discover the MIME type
|
|
class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
|
|
{
|
|
public:
|
|
LLMimeDiscoveryResponder( )
|
|
{}
|
|
|
|
|
|
|
|
virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
|
|
{
|
|
std::string media_type = content["content-type"].asString();
|
|
std::string::size_type idx1 = media_type.find_first_of(";");
|
|
std::string mime_type = media_type.substr(0, idx1);
|
|
completeAny(status, mime_type);
|
|
}
|
|
|
|
virtual void error( U32 status, const std::string& reason )
|
|
{
|
|
completeAny(status, "none/none");
|
|
}
|
|
|
|
void completeAny(U32 status, const std::string& mime_type)
|
|
{
|
|
LLViewerMedia::setMimeType(mime_type);
|
|
}
|
|
};
|
|
|
|
// static
|
|
void LLViewerParcelMedia::initClass()
|
|
{
|
|
LLMessageSystem* msg = gMessageSystem;
|
|
msg->setHandlerFunc("ParcelMediaCommandMessage", processParcelMediaCommandMessage );
|
|
msg->setHandlerFunc("ParcelMediaUpdate", processParcelMediaUpdate );
|
|
LLViewerParcelMediaAutoPlay::initClass();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// static
|
|
void LLViewerParcelMedia::update(LLParcel* parcel)
|
|
{
|
|
if (/*LLViewerMedia::hasMedia()*/ true)
|
|
{
|
|
// we have a player
|
|
if (parcel)
|
|
{
|
|
// we're in a parcel
|
|
bool new_parcel = false;
|
|
S32 parcelid = parcel->getLocalID();
|
|
LLUUID regionid = gAgent.getRegion()->getRegionID();
|
|
if (parcelid != sMediaParcelLocalID || regionid != sMediaRegionID)
|
|
{
|
|
sMediaParcelLocalID = parcelid;
|
|
sMediaRegionID = regionid;
|
|
new_parcel = true;
|
|
}
|
|
|
|
std::string mediaUrl = std::string ( parcel->getMediaURL () );
|
|
LLString::trim(mediaUrl);
|
|
|
|
// has something changed?
|
|
if ( ( LLViewerMedia::getMediaURL() != mediaUrl )
|
|
|| ( LLViewerMedia::getMediaTextureID() != parcel->getMediaID () ) )
|
|
{
|
|
bool video_was_playing = FALSE;
|
|
bool same_media_id = LLViewerMedia::getMediaTextureID() == parcel->getMediaID ();
|
|
|
|
if (LLViewerMedia::isMediaPlaying())
|
|
{
|
|
video_was_playing = TRUE;
|
|
}
|
|
|
|
if ( !mediaUrl.empty() && same_media_id && ! new_parcel)
|
|
{
|
|
// Someone has "changed the channel", changing the URL of a video
|
|
// you were already watching. Automatically play provided the texture ID is the same
|
|
if (video_was_playing)
|
|
{
|
|
// Poke the mime type in before calling play.
|
|
// This is necessary because in this instance we are not waiting
|
|
// for the results of a header curl. In order to change the channel
|
|
// a mime type MUST be provided.
|
|
LLViewerMedia::setMimeType(parcel->getMediaType());
|
|
play(parcel);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
stop();
|
|
}
|
|
|
|
// Discover the MIME type
|
|
// Disabled for the time being. Get the mime type from the parcel.
|
|
if(gSavedSettings.getBOOL("AutoMimeDiscovery"))
|
|
{
|
|
LLHTTPClient::getHeaderOnly( mediaUrl, new LLMimeDiscoveryResponder());
|
|
}
|
|
else
|
|
{
|
|
LLViewerMedia::setMimeType(parcel->getMediaType());
|
|
}
|
|
|
|
// First use warning
|
|
if( gSavedSettings.getWarning("FirstStreamingVideo") )
|
|
{
|
|
gViewerWindow->alertXml("ParcelCanPlayMedia",
|
|
callback_play_media, (void*)parcel);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
stop();
|
|
}
|
|
}
|
|
/*
|
|
else
|
|
{
|
|
// no audio player, do a first use dialog if their is media here
|
|
if (parcel)
|
|
{
|
|
std::string mediaUrl = std::string ( parcel->getMediaURL () );
|
|
if (!mediaUrl.empty ())
|
|
{
|
|
if (gSavedSettings.getWarning("QuickTimeInstalled"))
|
|
{
|
|
gSavedSettings.setWarning("QuickTimeInstalled", FALSE);
|
|
|
|
LLNotifyBox::showXml("NoQuickTime" );
|
|
};
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
// static
|
|
void LLViewerParcelMedia::play(LLParcel* parcel)
|
|
{
|
|
lldebugs << "LLViewerParcelMedia::play" << llendl;
|
|
|
|
if (!parcel) return;
|
|
|
|
if (!gSavedSettings.getBOOL("AudioStreamingVideo"))
|
|
return;
|
|
|
|
std::string media_url = parcel->getMediaURL();
|
|
std::string mime_type = parcel->getMediaType();
|
|
LLUUID placeholder_texture_id = parcel->getMediaID();
|
|
U8 media_auto_scale = parcel->getMediaAutoScale();
|
|
U8 media_loop = parcel->getMediaLoop();
|
|
S32 media_width = parcel->getMediaWidth();
|
|
S32 media_height = parcel->getMediaHeight();
|
|
LLViewerMedia::play(media_url, mime_type, placeholder_texture_id,
|
|
media_width, media_height, media_auto_scale,
|
|
media_loop);
|
|
LLFirstUse::useMedia();
|
|
|
|
LLViewerParcelMediaAutoPlay::playStarted();
|
|
}
|
|
|
|
// static
|
|
void LLViewerParcelMedia::stop()
|
|
{
|
|
|
|
LLViewerMedia::stop();
|
|
}
|
|
|
|
// static
|
|
void LLViewerParcelMedia::pause()
|
|
{
|
|
LLViewerMedia::pause();
|
|
}
|
|
|
|
// static
|
|
void LLViewerParcelMedia::start()
|
|
{
|
|
LLViewerMedia::start();
|
|
LLFirstUse::useMedia();
|
|
|
|
LLViewerParcelMediaAutoPlay::playStarted();
|
|
}
|
|
|
|
// static
|
|
void LLViewerParcelMedia::seek(F32 time)
|
|
{
|
|
LLViewerMedia::seek(time);
|
|
}
|
|
|
|
|
|
// static
|
|
LLMediaBase::EStatus LLViewerParcelMedia::getStatus()
|
|
{
|
|
return LLViewerMedia::getStatus();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// static
|
|
void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg, void ** )
|
|
{
|
|
// extract the agent id
|
|
// LLUUID agent_id;
|
|
// msg->getUUID( agent_id );
|
|
|
|
U32 flags;
|
|
U32 command;
|
|
F32 time;
|
|
msg->getU32( "CommandBlock", "Flags", flags );
|
|
msg->getU32( "CommandBlock", "Command", command);
|
|
msg->getF32( "CommandBlock", "Time", time );
|
|
|
|
if (flags &( (1<<PARCEL_MEDIA_COMMAND_STOP)
|
|
| (1<<PARCEL_MEDIA_COMMAND_PAUSE)
|
|
| (1<<PARCEL_MEDIA_COMMAND_PLAY)
|
|
| (1<<PARCEL_MEDIA_COMMAND_LOOP)
|
|
| (1<<PARCEL_MEDIA_COMMAND_UNLOAD) ))
|
|
{
|
|
// stop
|
|
if( command == PARCEL_MEDIA_COMMAND_STOP )
|
|
{
|
|
stop();
|
|
}
|
|
else
|
|
// pause
|
|
if( command == PARCEL_MEDIA_COMMAND_PAUSE )
|
|
{
|
|
pause();
|
|
}
|
|
else
|
|
// play
|
|
if(( command == PARCEL_MEDIA_COMMAND_PLAY ) ||
|
|
( command == PARCEL_MEDIA_COMMAND_LOOP ))
|
|
{
|
|
if (LLViewerMedia::isMediaPaused())
|
|
{
|
|
start();
|
|
}
|
|
else
|
|
{
|
|
LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
|
play(parcel);
|
|
}
|
|
}
|
|
else
|
|
// unload
|
|
if( command == PARCEL_MEDIA_COMMAND_UNLOAD )
|
|
{
|
|
stop();
|
|
}
|
|
}
|
|
|
|
if (flags & (1<<PARCEL_MEDIA_COMMAND_TIME))
|
|
{
|
|
if(! LLViewerMedia::hasMedia())
|
|
{
|
|
LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
|
play(parcel);
|
|
}
|
|
seek(time);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// static
|
|
void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void ** )
|
|
{
|
|
LLUUID media_id;
|
|
std::string media_url;
|
|
std::string media_type;
|
|
S32 media_width = 0;
|
|
S32 media_height = 0;
|
|
U8 media_auto_scale = FALSE;
|
|
U8 media_loop = FALSE;
|
|
|
|
msg->getUUID( "DataBlock", "MediaID", media_id );
|
|
char media_url_buffer[257];
|
|
msg->getString( "DataBlock", "MediaURL", 255, media_url_buffer );
|
|
media_url = media_url_buffer;
|
|
msg->getU8("DataBlock", "MediaAutoScale", media_auto_scale);
|
|
|
|
if (msg->getNumberOfBlocks("DataBlockExtended")) // do we have the extended data?
|
|
{
|
|
char media_type_buffer[257];
|
|
msg->getString("DataBlockExtended", "MediaType", 255, media_type_buffer);
|
|
media_type = media_type_buffer;
|
|
msg->getU8("DataBlockExtended", "MediaLoop", media_loop);
|
|
msg->getS32("DataBlockExtended", "MediaWidth", media_width);
|
|
msg->getS32("DataBlockExtended", "MediaHeight", media_height);
|
|
}
|
|
|
|
LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
|
BOOL same = FALSE;
|
|
if (parcel)
|
|
{
|
|
same = ((parcel->getMediaURL() == media_url) &&
|
|
(parcel->getMediaType() == media_type) &&
|
|
(parcel->getMediaID() == media_id) &&
|
|
(parcel->getMediaWidth() == media_width) &&
|
|
(parcel->getMediaHeight() == media_height) &&
|
|
(parcel->getMediaAutoScale() == media_auto_scale) &&
|
|
(parcel->getMediaLoop() == media_loop));
|
|
|
|
if (!same)
|
|
{
|
|
// temporarily store these new values in the parcel
|
|
parcel->setMediaURL(media_url);
|
|
parcel->setMediaType(media_type.c_str());
|
|
parcel->setMediaID(media_id);
|
|
parcel->setMediaWidth(media_width);
|
|
parcel->setMediaHeight(media_height);
|
|
parcel->setMediaAutoScale(media_auto_scale);
|
|
parcel->setMediaLoop(media_loop);
|
|
|
|
play(parcel);
|
|
}
|
|
}
|
|
}
|
|
|
|
void callback_play_media(S32 option, void* data)
|
|
{
|
|
LLParcel* parcel = (LLParcel*)data;
|
|
if (option == 0)
|
|
{
|
|
gSavedSettings.setBOOL("AudioStreamingVideo", TRUE);
|
|
LLViewerParcelMedia::play(parcel);
|
|
}
|
|
else
|
|
{
|
|
gSavedSettings.setBOOL("AudioStreamingVideo", FALSE);
|
|
}
|
|
gSavedSettings.setWarning("FirstStreamingVideo", FALSE);
|
|
|
|
}
|
|
|