Large snapshot update (part 3)

This commit is contained in:
Aleric Inglewood
2012-12-22 19:07:08 +01:00
parent a9963bcdb3
commit 8095d6c48c
14 changed files with 396 additions and 239 deletions

View File

@@ -760,17 +760,17 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value)
setopt(option, value.c_str());
}
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size)
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive)
{
llassert_always(postdata->data());
DoutCurl("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\".");
setPostField(postdata); // Make sure the data stays around until we don't need it anymore.
setPost_raw(size, postdata->data());
setPost_raw(size, postdata->data(), keepalive);
}
void CurlEasyRequest::setPost_raw(U32 size, char const* data)
void CurlEasyRequest::setPost_raw(U32 size, char const* data, bool keepalive)
{
if (!data)
{
@@ -780,7 +780,7 @@ void CurlEasyRequest::setPost_raw(U32 size, char const* data)
// The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default.
addHeader("Expect:");
if (size > 0)
if (size > 0 && keepalive)
{
addHeader("Connection: keep-alive");
addHeader("Keep-alive: 300");

View File

@@ -270,11 +270,11 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
// and the CurlEasyRequest destructed.
class CurlEasyRequest : public CurlEasyHandle {
private:
void setPost_raw(U32 size, char const* data);
void setPost_raw(U32 size, char const* data, bool keepalive);
public:
void setPost(U32 size) { setPost_raw(size, NULL); }
void setPost(AIPostFieldPtr const& postdata, U32 size);
void setPost(char const* data, U32 size) { setPost(new AIPostField(data), size); }
void setPost(U32 size, bool keepalive = true) { setPost_raw(size, NULL, keepalive); }
void setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive = true);
void setPost(char const* data, U32 size, bool keepalive = true) { setPost(new AIPostField(data), size, keepalive); }
void setoptString(CURLoption option, std::string const& value);
void addHeader(char const* str);
void addHeaders(AIHTTPHeaders const& headers);

View File

@@ -2174,7 +2174,7 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const&
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
// Sanity check. If the server replies with a redirect status then we better have that option turned on!
if ((status >= 300 && status < 400) && mResponder && !mResponder->followRedir())
if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok())
{
llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl;
}

View File

@@ -201,6 +201,7 @@ static void request(
Injector* body_injector,
LLHTTPClient::ResponderPtr responder,
AIHTTPHeaders& headers,
EKeepAlive keepalive = keep_alive,
bool is_auth = false,
bool no_compression = false)
{
@@ -213,7 +214,7 @@ static void request(
LLURLRequest* req;
try
{
req = new LLURLRequest(method, url, body_injector, responder, headers, is_auth, no_compression);
req = new LLURLRequest(method, url, body_injector, responder, headers, keepalive, is_auth, no_compression);
}
catch(AICurlNoEasyHandle& error)
{
@@ -657,17 +658,17 @@ void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr re
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers);
}
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers);
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers, keepalive);
}
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, false); // Does use compression.
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, keepalive, true, false); // Does use compression.
}
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
{
XMLRPC_REQUEST xmlrpc_request = XMLRPC_RequestNew();
XMLRPC_RequestSetMethodName(xmlrpc_request, method);
@@ -675,22 +676,22 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC
XMLRPC_RequestSetData(xmlrpc_request, value);
// XMLRPCInjector takes ownership of xmlrpc_request and will free it when done.
// LLURLRequest takes ownership of the XMLRPCInjector object and will free it when done.
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, true); // Does not use compression.
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, keepalive, true, true); // Does not use compression.
}
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers);
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers, keepalive);
}
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers);
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers, keepalive);
}
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers)
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive)
{
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers);
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers, keepalive);
}
// static

View File

@@ -66,6 +66,11 @@ struct AIBufferedCurlEasyRequestEvents {
virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed.
};
enum EKeepAlive {
no_keep_alive = 0,
keep_alive
};
class LLHTTPClient {
public:
@@ -163,6 +168,9 @@ public:
// The default is not to follow redirections.
virtual bool followRedir(void) const { return false; }
// If this function returns false then we generate an error when a redirect status (300..399) is received.
virtual bool redirect_status_ok(void) const { return followRedir(); }
// Timeout policy to use.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0;
@@ -382,31 +390,31 @@ public:
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder)
{ AIHTTPHeaders headers; getHeaderOnly(url, responder, headers); }
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers);
static void post(std::string const& url, LLSD const& body, ResponderPtr responder)
{ AIHTTPHeaders headers; post(url, body, responder, headers); }
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; post(url, body, responder, headers, keepalive); }
/** Takes ownership of request and deletes it when sent */
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers);
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder)
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers); }
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers, keepalive); }
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers);
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder)
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers); }
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers, keepalive); }
/** Takes ownership of data and deletes it when sent */
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers);
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder)
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers); }
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers, keepalive); }
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers);
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder)
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers); }
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers, keepalive); }
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers);
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder)
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers); }
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers, EKeepAlive keepalive = keep_alive);
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers, keepalive); }
static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers);
static void del(std::string const& url, ResponderPtr responder)

View File

@@ -77,8 +77,8 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
// This might throw AICurlNoEasyHandle.
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body,
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression) :
mAction(action), mURL(url), mIsAuth(is_auth), mNoCompression(no_compression),
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression) :
mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(no_compression),
mBody(body), mResponder(responder), mHeaders(headers)
{
}
@@ -226,7 +226,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
case HTTP_POST:
{
// Set the handle for an http post
curlEasyRequest_w->setPost(mBodySize);
curlEasyRequest_w->setPost(mBodySize, mKeepAlive);
// Set Accept-Encoding to allow response compression
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : "");

View File

@@ -77,7 +77,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
* @param action One of the ERequestAction enumerations.
* @param url The url of the request. It should already be encoded.
*/
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression);
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression);
protected:
// Call abort(), not delete.
@@ -111,6 +111,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
private:
ERequestAction mAction;
std::string mURL;
bool mKeepAlive; // Set to false only when explicitely requested.
bool mIsAuth; // Set for authentication messages (login, buy land, buy currency).
bool mNoCompression; // Set to disable using gzip.
Injector* mBody; // Non-zero iff the action is HTTP_POST and HTTP_PUT.

View File

@@ -89,8 +89,8 @@
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
S32 LLFloaterSnapshot::sUIWinHeightLong = 609 ;
S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 250 ;
S32 LLFloaterSnapshot::sUIWinHeightLong = 619 ;
S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 260 ;
S32 LLFloaterSnapshot::sUIWinWidth = 219 ;
S32 const THUMBHEIGHT = 159;
@@ -123,6 +123,15 @@ public:
SNAPSHOT_LOCAL
};
enum EAspectSizeProblem
{
ASPECTSIZE_OK,
CANNOT_CROP_HORIZONTALLY,
CANNOT_CROP_VERTICALLY,
SIZE_TOO_LARGE,
CANNOT_RESIZE
};
U32 typeToMask(ESnapshotType type) const { return 1 << type; }
void addUsedBy(ESnapshotType type) { mUsedBy |= typeToMask(type); }
bool isUsedBy(ESnapshotType type) const { return (mUsedBy & typeToMask(type)) != 0; }
@@ -140,7 +149,7 @@ public:
void getSize(S32& w, S32& h) const;
void setAspect(F32 a);
F32 getAspect() const;
void getUsedSize(S32& w, S32& h) const;
void getRawSize(S32& w, S32& h) const;
S32 getDataSize() const { return mFormattedDataSize; }
void setMaxImageSize(S32 size) ;
S32 getMaxImageSize() {return mMaxImageSize ;}
@@ -178,11 +187,12 @@ public:
BOOL setThumbnailImageSize();
void generateThumbnailImage();
EAspectSizeProblem getAspectSizeProblem(S32& width_out, S32& height_out, bool& crop_vertically_out, S32& crop_offset_out);
void generateFormattedAndFullscreenPreview(bool delayed_formatted = false);
void drawPreviewRect(S32 offset_x, S32 offset_y) ;
// Returns TRUE when snapshot generated, FALSE otherwise.
static BOOL onIdle( void* snapshot_preview );
static BOOL onIdle(LLSnapshotLivePreview* previewp);
private:
LLColor4 mColor;
@@ -320,7 +330,6 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) :
DoutEntering(dc::notice, "LLSnapshotLivePreview() [" << (void*)this << "]");
setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
mSnapshotDelayTimer.start();
// gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
sList.insert(this);
setFollowsAll();
mWidth = gViewerWindow->getWindowDisplayWidth();
@@ -343,8 +352,6 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview()
// delete images
mRawSnapshot = NULL;
mFormattedImage = NULL;
// gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );
sList.erase(this);
}
@@ -766,10 +773,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(void)
// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
// Returns TRUE if new snapshot generated, FALSE otherwise.
//static
BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
BOOL LLSnapshotLivePreview::onIdle(LLSnapshotLivePreview* previewp)
{
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
@@ -796,7 +801,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
if (previewp->mFormattedDelayTimer.getStarted() && previewp->mFormattedDelayTimer.hasExpired())
{
previewp->mFormattedDelayTimer.stop();
previewp->generateFormattedAndFullscreenPreview();
LLFloaterSnapshot::updateControls();
}
return FALSE;
}
@@ -861,71 +866,85 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
return TRUE;
}
void LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(bool delayed)
LLSnapshotLivePreview::EAspectSizeProblem LLSnapshotLivePreview::getAspectSizeProblem(S32& width_out, S32& height_out, bool& crop_vertically_out, S32& crop_offset_out)
{
DoutEntering(dc::notice, "LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(" << delayed << ")");
mFormattedUpToDate = false;
S32 const window_width = gViewerWindow->getWindowWidthRaw();
S32 const window_height = gViewerWindow->getWindowHeightRaw();
// We need an image with the aspect mAspectRatio (from which mWidth and mHeight were derived).
// The current aspect ratio of mRawSnapshot is:
F32 raw_aspect = (F32)mRawSnapshotWidth / mRawSnapshotHeight;
F32 const raw_aspect = (F32)mRawSnapshotWidth / mRawSnapshotHeight;
// Find out if mRawSnapshot was cropped already.
bool allow_vertical_crop = window_height * raw_aspect >= window_width; // mRawSnapshot was cropped horizontally.
bool allow_horizontal_crop = window_width / raw_aspect >= window_height; // mRawSnapshot was cropped vertically.
bool crop_vertically = true; // Prefer this, as it is faster.
S32 crop_offset = 0; // The number of columns or rows to cut off on the left or bottom.
bool const allow_vertical_crop = window_height * raw_aspect >= window_width; // mRawSnapshot was cropped horizontally.
bool const allow_horizontal_crop = window_width / raw_aspect >= window_height; // mRawSnapshot was cropped vertically.
crop_vertically_out = true; // Prefer this, as it is faster.
crop_offset_out = 0; // The number of columns or rows to cut off on the left or bottom.
// Construct a rectangle size w,h that fits inside mRawSnapshot but has the correct aspect.
S32 w = mRawSnapshotWidth;
S32 h = mRawSnapshotHeight;
width_out = mRawSnapshotWidth;
height_out = mRawSnapshotHeight;
if (mAspectRatio < raw_aspect)
{
w = llround(w * mAspectRatio / raw_aspect);
if (w < mRawSnapshotWidth)
width_out = llround(width_out * mAspectRatio / raw_aspect);
if (width_out < mRawSnapshotWidth)
{
// Only set this to false when there is actually something to crop.
crop_vertically = false;
crop_vertically_out = false;
if (!allow_horizontal_crop)
{
Dout(dc::notice, "NOT up to date: required aspect " << mAspectRatio <<
" is less than raw aspect " << raw_aspect << " which is already vertically cropped.");
return;
return CANNOT_CROP_HORIZONTALLY;
}
crop_offset = (mRawSnapshotWidth - w) / 2;
crop_offset_out = (mRawSnapshotWidth - width_out) / 2;
}
}
else if (mAspectRatio > raw_aspect)
{
h = llround(h * raw_aspect / mAspectRatio);
if (h < mRawSnapshotHeight)
height_out = llround(height_out * raw_aspect / mAspectRatio);
if (height_out < mRawSnapshotHeight)
{
if (!allow_vertical_crop)
{
Dout(dc::notice, "NOT up to date: required aspect " << mAspectRatio <<
" is larger than raw aspect " << raw_aspect << " which is already horizontally cropped.");
return;
return CANNOT_CROP_VERTICALLY;
}
crop_offset = (mRawSnapshotHeight - h) / 2;
crop_offset_out = (mRawSnapshotHeight - height_out) / 2;
}
}
// Never allow upscaling of the existing snapshot, of course.
if (mWidth > w || mHeight > h)
if (mWidth > width_out || mHeight > height_out)
{
Dout(dc::notice, "NOT up to date: required target size " << mWidth << "x" << mHeight <<
" is larger than (cropped) raw snapshot with size " << w << "x" << h << "!");
return;
" is larger than (cropped) raw snapshot with size " << width_out << "x" << height_out << "!");
return SIZE_TOO_LARGE;
}
// Do not allow any resizing for target images that are equal or larger than the current window, when the target is the harddisk.
// If the target size is smaller, than a resize would occur anyway, so in that case we allow resizing whatever we have.
if (mSnapshotType == SNAPSHOT_LOCAL && (mWidth >= window_width || mHeight >= window_height) && (mWidth != w || mHeight != h))
// If the target size is smaller, than a resize would occur anyway, so in that case we allow resizing whatever we have,
// unless the aspect is different in which case we have to allow resizing in one direction.
if (mSnapshotType == SNAPSHOT_LOCAL && (mWidth >= window_width || mHeight >= window_height) && mWidth != width_out && mHeight != height_out)
{
Dout(dc::notice, "NOT up to date: required target size " << mWidth << "x" << mHeight <<
" is larger or equal the window size (" << window_width << "x" << window_height << ")"
" but unequal the (cropped) raw snapshot size (" << w << "x" << h << ")"
" but unequal the (cropped) raw snapshot size (" << width_out << "x" << height_out << ")"
" and target is disk!");
return CANNOT_RESIZE;
}
return ASPECTSIZE_OK;
}
void LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(bool delayed)
{
DoutEntering(dc::notice, "LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(" << delayed << ")");
mFormattedUpToDate = false;
S32 w, h, crop_offset;
bool crop_vertically;
EAspectSizeProblem ret = getAspectSizeProblem(w, h, crop_vertically, crop_offset);
if (ret != ASPECTSIZE_OK)
{
// Current raw snapshot cannot be used.
return;
}
@@ -933,16 +952,20 @@ void LLSnapshotLivePreview::generateFormattedAndFullscreenPreview(bool delayed)
LLFloaterSnapshot::ESnapshotFormat format;
switch (mSnapshotType)
{
case SNAPSHOT_FEED:
// Feeds hardcoded to always use png.
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG;
break;
case SNAPSHOT_POSTCARD:
// Postcards hardcoded to always use jpeg.
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
break;
case SNAPSHOT_TEXTURE:
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_J2C;
break;
case SNAPSHOT_LOCAL:
format = mSnapshotFormat;
break;
default:
// Feeds and postcards hardcoded to always use jpeg.
format = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG;
break;
}
if (mFormattedImage &&
@@ -1151,7 +1174,7 @@ F32 LLSnapshotLivePreview::getAspect() const
return mAspectRatio;
}
void LLSnapshotLivePreview::getUsedSize(S32& w, S32& h) const
void LLSnapshotLivePreview::getRawSize(S32& w, S32& h) const
{
w = mRawSnapshotWidth;
h = mRawSnapshotHeight;
@@ -1391,7 +1414,7 @@ public:
static void onQualityMouseUp(void* data);
static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater);
static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls = true);
static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls = true);
static void setAspect(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls = true);
static void updateControls(LLFloaterSnapshot* floater, bool delayed_formatted = false);
static void updateLayout(LLFloaterSnapshot* floater);
@@ -1455,10 +1478,10 @@ LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFlo
}
// static
void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls)
void LLFloaterSnapshot::Impl::setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls)
{
LLComboBox* combo = floater->getChild<LLComboBox>(comboname);
combo->setVisible(TRUE);
combo->setVisible(visible);
updateResolution(combo, floater, update_controls); // to sync spinners with combo
}
@@ -1479,34 +1502,27 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution
{
floaterp->getChild<LLComboBox>("feed_size_combo")->setCurrentByIndex(0);
gSavedSettings.setS32("SnapshotFeedLastResolution", 0);
floaterp->getChild<LLComboBox>("feed_aspect_combo")->setCurrentByIndex(0); // 4:3
floaterp->getChild<LLComboBox>("feed_size_combo")->setCurrentByIndex(2); // 500x375
gSavedSettings.setS32("SnapshotFeedLastResolution", 2);
floaterp->getChild<LLComboBox>("feed_aspect_combo")->setCurrentByIndex(0); // Default (500x375)
gSavedSettings.setS32("SnapshotFeedLastAspect", 0);
floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0);
floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0); // Current window
gSavedSettings.setS32("SnapshotPostcardLastResolution", 0);
floaterp->getChild<LLComboBox>("postcard_aspect_combo")->setCurrentByIndex(0); // Default (current window)
gSavedSettings.setS32("SnapshotPostcardLastAspect", 0);
floaterp->getChild<LLComboBox>("texture_size_combo")->setCurrentByIndex(0);
floaterp->getChild<LLComboBox>("texture_size_combo")->setCurrentByIndex(0); // 512x512 (most likely result for current window).
gSavedSettings.setS32("SnapshotTextureLastResolution", 0);
floaterp->getChild<LLComboBox>("texture_aspect_combo")->setCurrentByIndex(0); // Current window
gSavedSettings.setS32("SnapshotTextureLastAspect", 0);
floaterp->getChild<LLComboBox>("local_size_combo")->setCurrentByIndex(0);
floaterp->getChild<LLComboBox>("local_size_combo")->setCurrentByIndex(0); // Current window
gSavedSettings.setS32("SnapshotLocalLastResolution", 0);
floaterp->getChild<LLComboBox>("local_aspect_combo")->setCurrentByIndex(0); // Current window
gSavedSettings.setS32("SnapshotLocalLastAspect", 0);
LLSnapshotLivePreview* previewp = getPreviewView(floaterp);
S32 w, h;
previewp->getSize(w, h);
if (gViewerWindow->getWindowDisplayWidth() != w || gViewerWindow->getWindowDisplayHeight() != h)
{
previewp->setSize(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
updateControls(floaterp);
}
updateControls(floaterp);
}
if (gSavedSettings.getBOOL("UseFreezeTime"))
@@ -1629,26 +1645,21 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de
previewp->setSnapshotBufferType(floater, layer_type);
}
BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot");
if (is_advance)
switch(shot_type)
{
switch(shot_type)
{
case LLSnapshotLivePreview::SNAPSHOT_FEED:
setResolution(floater, "feed_size_combo", false);
break;
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
setResolution(floater, "postcard_size_combo", false);
break;
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
setResolution(floater, "texture_size_combo", false);
break;
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
setResolution(floater, "local_size_combo", false);
break;
}
floater->getChild<LLComboBox>(previewp->aspectComboName())->setVisible(TRUE);
case LLSnapshotLivePreview::SNAPSHOT_FEED:
setResolution(floater, "feed_size_combo", is_advance, false);
break;
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
setResolution(floater, "postcard_size_combo", is_advance, false);
break;
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
setResolution(floater, "texture_size_combo", is_advance, false);
break;
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
setResolution(floater, "local_size_combo", is_advance, false);
break;
}
floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(shot_format);
floater->childSetVisible("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE);
@@ -1658,11 +1669,11 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de
floater->childSetEnabled("layer_types", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL);
BOOL is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL;
BOOL show_slider =
shot_type == LLSnapshotLivePreview::SNAPSHOT_FEED ||
BOOL show_slider =
shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD ||
(is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
floater->getChild<LLComboBox>(previewp->aspectComboName())->setVisible(is_advance);
floater->childSetVisible("more_btn", !is_advance); // the only item hidden in advanced mode
floater->childSetVisible("less_btn", is_advance);
floater->childSetVisible("type_label2", is_advance);
@@ -1671,6 +1682,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de
floater->childSetVisible("local_format_combo", is_local);
floater->childSetVisible("layer_types", is_advance);
floater->childSetVisible("layer_type_label", is_advance);
floater->childSetVisible("aspect_one_label", is_advance);
floater->childSetVisible("snapshot_width", is_advance);
floater->childSetVisible("snapshot_height", is_advance);
floater->childSetVisible("aspect_ratio", is_advance);
@@ -2136,59 +2148,128 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
return;
}
S32 used_w = 0;
S32 used_h = 0;
S32 new_width = 0;
S32 new_height = 0;
F32 new_aspect = 0;
LLSnapshotLivePreview* previewp = getPreviewView(view);
LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType");
#if 0 // AIFIXME
bool up_to_date_now = false;
bool up_to_date_after_toggling = false;
if (previewp && previewp->isUsed() && !previewp->isOverriddenBy(shot_type))
// Is the snapshot was already used (saved or uploaded) and no manual changes
// have been made since to the current destination type, and the raw snapshot
// is still up to date with regard to visibility of UI, HUD and BufferType etc?
if (previewp && previewp->isUsed() && !previewp->isOverriddenBy(shot_type) && previewp->getRawSnapshotUpToDate())
{
up_to_date_now = previewp->getSnapshotUpToDateExceptForSize();
previewp->mScaleInsteadOfCrop = !previewp->mScaleInsteadOfCrop;
up_to_date_after_toggling = previewp->getSnapshotUpToDateExceptForSize();
previewp->mScaleInsteadOfCrop = !previewp->mScaleInsteadOfCrop;
}
if (up_to_date_now || up_to_date_after_toggling)
{
// need_keep_aspect is set when mScaleInsteadOfCrop makes a difference.
bool need_keep_aspect = up_to_date_now != up_to_date_after_toggling;
// Force the size, and possibly mScaleInsteadOfCrop, to be the one of the existing snapshot.
previewp->getUsedSize(used_w, used_h);
LLComboBox* size_combo_box = NULL;
LLComboBox* aspect_combo_box = NULL;
switch(shot_type)
previewp->getSize(new_width, new_height);
new_aspect = previewp->getAspect();
S32 const old_width = new_width;
S32 const old_height = new_height;
F32 const old_aspect = new_aspect;
S32 raw_width;
S32 raw_height;
previewp->getRawSize(raw_width, raw_height);
F32 const raw_aspect = (F32)raw_width / raw_height;
bool fixed_crop = false;
bool fixed_size = false;
bool fixed_scale = false;
bool done = false;
bool fail = false;
while (!done)
{
case LLSnapshotLivePreview::SNAPSHOT_FEED:
size_combo_box = view->getChild<LLComboBox>("feed_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("feed_aspect_combo");
// Attempt to change the size and aspect so the raw snapshot can also be used for this new destination.
S32 w, h, crop_offset;
bool crop_vertically;
previewp->setSize(new_width, new_height);
previewp->setAspect(new_aspect);
LLSnapshotLivePreview::EAspectSizeProblem ret = previewp->getAspectSizeProblem(w, h, crop_vertically, crop_offset);
switch(ret)
{
case LLSnapshotLivePreview::ASPECTSIZE_OK:
done = true; // Don't change anything (else) if the current settings are usable.
break;
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
size_combo_box = view->getChild<LLComboBox>("postcard_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("postcard_aspect_combo");
case LLSnapshotLivePreview::CANNOT_CROP_HORIZONTALLY:
case LLSnapshotLivePreview::CANNOT_CROP_VERTICALLY:
if (fixed_crop)
{
done = fail = true;
}
else
{
// Set target aspect to aspect of the raw snapshot we have (no reason to crop anything).
new_aspect = raw_aspect;
fixed_crop = true;
}
break;
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
size_combo_box = view->getChild<LLComboBox>("texture_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("texture_aspect_combo");
case LLSnapshotLivePreview::SIZE_TOO_LARGE:
if (fixed_size)
{
done = fail = true;
}
else
{
if (new_width > w)
{
new_width = w;
new_height = llround(new_width / new_aspect);
}
if (new_height > h)
{
new_width = llmin(w, llround(h * new_aspect));
new_height = llmin(h, llround(new_width / new_aspect));
}
fixed_size = true;
}
break;
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
size_combo_box = view->getChild<LLComboBox>("local_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("local_aspect_combo");
case LLSnapshotLivePreview::CANNOT_RESIZE:
if (fixed_scale)
{
done = fail = true;
}
else
{
F32 ratio = llmin((F32)w / new_width, (F32)h / new_height);
new_width = llround(new_width * ratio);
new_height = llround(new_height * ratio);
fixed_scale = true;
}
break;
}
}
S32 index = 0;
bool keep_aspect = true;
bool needed_keep_aspect = up_to_date_now ? previewp->mScaleInsteadOfCrop : !previewp->mScaleInsteadOfCrop; // Only valid if need_keep_aspect is true.
S32 const custom = size_combo_box->getItemCount() - (shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE ? 0 : 1); // Texture does not end on 'Custom'.
while (index < custom)
previewp->setAspect(old_aspect);
previewp->setSize(old_width, old_height);
if (fail)
{
if (!need_keep_aspect || keep_aspect == needed_keep_aspect)
new_aspect = 0;
new_width = new_height = 0;
}
else
{
LLComboBox* size_combo_box = NULL;
LLComboBox* aspect_combo_box = NULL;
switch(shot_type)
{
case LLSnapshotLivePreview::SNAPSHOT_FEED:
size_combo_box = view->getChild<LLComboBox>("feed_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("feed_aspect_combo");
break;
case LLSnapshotLivePreview::SNAPSHOT_POSTCARD:
size_combo_box = view->getChild<LLComboBox>("postcard_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("postcard_aspect_combo");
break;
case LLSnapshotLivePreview::SNAPSHOT_TEXTURE:
size_combo_box = view->getChild<LLComboBox>("texture_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("texture_aspect_combo");
break;
case LLSnapshotLivePreview::SNAPSHOT_LOCAL:
size_combo_box = view->getChild<LLComboBox>("local_size_combo");
aspect_combo_box = view->getChild<LLComboBox>("local_aspect_combo");
break;
}
S32 index = 0;
S32 const size_custom = size_combo_box->getItemCount() - (shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE ? 0 : 1); // Texture does not end on 'Custom'.
while (index < size_custom)
{
size_combo_box->setCurrentByIndex(index);
std::string sdstring = combobox->getSelectedValue();
std::string sdstring = size_combo_box->getSelectedValue();
LLSD sdres;
std::stringstream sstream(sdstring);
LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
@@ -2199,35 +2280,57 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
width = gViewerWindow->getWindowDisplayWidth();
height = gViewerWindow->getWindowDisplayHeight();
}
if (width == used_w && height == used_h)
if (width == new_width && height == new_height)
{
break;
}
++index;
}
++index;
keep_aspect = false;
}
if (index == custom)
{
size_combo_box->setCurrentByIndex(index);
if (need_keep_aspect)
if (index == size_custom && shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE)
{
// Change mScaleInsteadOfCrop to needed_keep_aspect.
gSavedSettings.setBOOL("KeepAspectForSnapshot", needed_keep_aspect);
size_combo_box->setCurrentByIndex(index);
}
index = 0;
S32 const aspect_custom = aspect_combo_box->getItemCount() - 1;
while (index < aspect_custom)
{
aspect_combo_box->setCurrentByIndex(index);
std::string sdstring = aspect_combo_box->getSelectedValue();
std::stringstream sstream;
sstream << sdstring;
F32 aspect;
sstream >> aspect;
if (aspect == -2) // Default
{
aspect = (F32)new_width / new_height;
}
if (aspect == 0) // Current window
{
aspect = (F32)gViewerWindow->getWindowDisplayWidth() / gViewerWindow->getWindowDisplayHeight();
}
if (llabs(aspect - new_aspect) < 0.0001)
{
break;
}
++index;
}
if (index == aspect_custom)
{
aspect_combo_box->setCurrentByIndex(index);
setAspect(view, previewp->aspectComboName(), update_controls);
}
}
}
else
#endif
{
view->getChild<LLComboBox>("feed_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastResolution"));
view->getChild<LLComboBox>("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect"));
view->getChild<LLComboBox>("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution"));
view->getChild<LLComboBox>("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect"));
view->getChild<LLComboBox>("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution"));
view->getChild<LLComboBox>("texture_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastAspect"));
view->getChild<LLComboBox>("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution"));
view->getChild<LLComboBox>("local_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastAspect"));
view->getChild<LLComboBox>("feed_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastResolution"));
view->getChild<LLComboBox>("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect"));
view->getChild<LLComboBox>("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution"));
view->getChild<LLComboBox>("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect"));
view->getChild<LLComboBox>("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution"));
view->getChild<LLComboBox>("texture_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastAspect"));
view->getChild<LLComboBox>("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution"));
view->getChild<LLComboBox>("local_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastAspect"));
}
std::string sdstring = combobox->getSelectedValue();
@@ -2249,9 +2352,9 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
}
else if (width == -1 || height == -1)
{
if (previewp->isUsed() && used_w != 0 && used_h != 0)
if (previewp->isUsed() && new_width != 0 && new_height != 0)
{
previewp->setSize(used_w, used_h);
previewp->setSize(new_width, new_height);
}
else
{
@@ -2299,8 +2402,17 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool
if (previewp)
{
// In case the aspect is 'Default', need to update aspect (which will call updateControls, if necessary).
setAspect(view, previewp->aspectComboName(), update_controls);
if (new_aspect == 0)
{
// In case the aspect is 'Default', need to update aspect (which will call updateControls, if necessary).
setAspect(view, previewp->aspectComboName(), update_controls);
}
else
{
LLSpinCtrl* aspect_spinner = view->getChild<LLSpinCtrl>("aspect_ratio");
aspect_spinner->set(new_aspect);
previewp->setAspect(new_aspect);
}
}
}
@@ -2316,7 +2428,6 @@ void LLFloaterSnapshot::Impl::updateAspect(LLUICtrl* ctrl, void* data, bool upda
}
LLSnapshotLivePreview* previewp = getPreviewView(view);
//LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType");
view->getChild<LLComboBox>("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect"));
view->getChild<LLComboBox>("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect"));
@@ -2742,6 +2853,12 @@ void LLFloaterSnapshot::update()
}
}
//static
void LLFloaterSnapshot::updateControls()
{
Impl::updateControls(sInstance);
}
BOOL LLFloaterSnapshot::handleKeyHere(KEY key, MASK mask)
{
static const LLCachedControl<bool> freeze_time("FreezeTime",false);

View File

@@ -75,6 +75,8 @@ public:
static void saveLocalDone(bool success);
static void saveFeedDone(bool success);
static void updateControls();
private:
class Impl;
Impl& impl;

View File

@@ -55,6 +55,7 @@
#include "llwindow.h"
#include "llvieweraudio.h"
#include "llweb.h"
#include "llwebprofile.h"
#include "llfloateravatarinfo.h" // for getProfileURL() function
//#include "viewerversion.h"
@@ -182,11 +183,37 @@ public:
LL_INFOS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
LL_INFOS("MediaAuth") << headers << LL_ENDL;
bool found = false;
AIHTTPReceivedHeaders::range_type cookies;
if (headers.getValues("set-cookie", cookies))
{
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
{
LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost);
// The should be only one set-cookie header, and the key should be '_my_secondlife_session'.
// However, lets be a little more flexible. We look for the first header with a key that
// contains the string 'session'.
std::string key = cookie->second.substr(0, cookie->second.find('='));
if (key.find("session") != std::string::npos)
{
// Set cookie for snapshot publishing.
std::string auth_cookie = cookie->second.substr(0, cookie->second.find(";")); // strip path
if (found)
{
llwarns << "LLViewerMediaWebProfileResponder received more than one *session* cookie!?!" << llendl;
}
else
{
LL_INFOS("MediaAuth") << "Setting openID auth cookie \"" << auth_cookie << "\"." << LL_ENDL;
LLWebProfile::setAuthCookie(auth_cookie);
found = true;
}
}
}
}
if (!found)
{
llwarns << "LLViewerMediaWebProfileResponder did not receive a session ID cookie! OpenID authentications will fail!" << llendl;
}
}

View File

@@ -1340,7 +1340,7 @@ void LLViewerObjectList::killAllObjects()
killObject(objectp);
// Object must be dead, or it's the LLVOAvatarSelf which never dies.
llassert((objectp == gAgentAvatarp) || objectp->isDead());
llassert((objectp == gAgentAvatarp) || objectp->isDead() || (objectp->asAvatar() && objectp->asAvatar()->isFrozenDead()));
}
cleanDeadObjects(FALSE);

View File

@@ -341,6 +341,7 @@ public:
BOOL hasGray() const;
S32 getRezzedStatus() const; // 0 = cloud, 1 = gray, 2 = fully textured.
void updateRezzedStatusTimers();
bool isFrozenDead() const { return mFreezeTimeDead; }
S32 mLastRezzedStatus;
protected:

View File

@@ -114,7 +114,7 @@ public:
config["caption"] = data.get("caption", "").asString();
// Do the actual image upload using the configuration.
LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << llendl;
LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << LL_ENDL;
LLWebProfile::post(mImagep, config, upload_url);
}
@@ -151,7 +151,7 @@ public:
strstrm << istr.rdbuf();
const std::string body = strstrm.str();
llinfos << "Image uploaded." << llendl;
LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << llendl;
LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << LL_ENDL;
LLWebProfile::reportImageUploadStatus(true);
}
@@ -173,10 +173,11 @@ class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responde
public:
/*virtual*/ bool needsHeaders(void) const { return true; }
/*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
/*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& received_headers)
{
// Viewer seems to fail to follow a 303 redirect on POST request
// (URLRequest Error: 65, Send failed since rewinding of the data stream failed).
// Server abuses 303 status; Curl can't handle it because it tries to resent
// the just uploaded data, which fails
// (CURLE_SEND_FAIL_REWIND: Send failed since rewinding of the data stream failed).
// Handle it manually.
if (status == 303)
{
@@ -184,14 +185,15 @@ public:
headers.addHeader("Accept", "*/*");
headers.addHeader("Cookie", LLWebProfile::getAuthCookie());
headers.addHeader("User-Agent", LLViewerMedia::getCurrentUserAgent());
const std::string& redir_url = content["location"];
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl;
std::string redir_url;
received_headers.getFirstValue("location", redir_url);
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL;
LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
}
else
{
llwarns << "Unexpected POST status: " << status << " " << reason << llendl;
LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl;
LL_DEBUGS("Snapshots") << "received_headers: [" << received_headers << "]" << LL_ENDL;
LLWebProfile::reportImageUploadStatus(false);
}
}
@@ -205,7 +207,7 @@ public:
protected:
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return webProfileResponders_timeout; }
/*virtual*/ bool followRedir(void) const { return true; }
/*virtual*/ bool redirect_status_ok(void) const { return true; }
};
///////////////////////////////////////////////////////////////////////////////
@@ -222,7 +224,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
config_url += "?caption=" + LLURI::escape(caption);
config_url += "&add_loc=" + std::string(add_location ? "1" : "0");
LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl;
LL_DEBUGS("Snapshots") << "Requesting " << config_url << LL_ENDL;
AIHTTPHeaders headers;
headers.addHeader("Accept", "*/*");
headers.addHeader("Cookie", LLWebProfile::getAuthCookie());
@@ -233,7 +235,7 @@ void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::str
// static
void LLWebProfile::setAuthCookie(const std::string& cookie)
{
LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << llendl;
LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << LL_ENDL;
sAuthCookie = cookie;
}
@@ -289,24 +291,22 @@ void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, c
body << "--" << boundary << "\r\n"
<< "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n"
<< "Content-Type: image/png\r\n\r\n";
size_t const body_size = body.str().size();
// Insert the image data.
// *FIX: Treating this as a string will probably screw it up ...
U8* image_data = image->getData();
for (S32 i = 0; i < image->getDataSize(); ++i)
{
body << image_data[i];
}
body << "\r\n--" << boundary << "--\r\n";
std::ostringstream footer;
footer << "\r\n--" << boundary << "--\r\n";
size_t const footer_size = footer.str().size();
size_t size = body_size + image->getDataSize() + footer_size;
// postRaw() takes ownership of the buffer and releases it later.
size_t size = body.str().size();
char* data = new char [size];
memcpy(data, body.str().data(), size);
memcpy(data, body.str().data(), body_size);
// Insert the image data.
memcpy(data + body_size, image->getData(), image->getDataSize());
memcpy(data + body_size + image->getDataSize(), footer.str().data(), footer_size);
// Send request, successful upload will trigger posting metadata.
LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers);
LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers, no_keep_alive);
}
// static

View File

@@ -53,11 +53,11 @@
<button bottom_delta="-22" follows="left|top" font="SansSerifSmall" halign="center"
height="20" label="Advanced&gt;&gt;" left="10"
mouse_opaque="true" name="more_btn" scale_image="TRUE"
tool_tip="Advanced Options. Default uses current window size." width="72" />
tool_tip="Advanced Options. Default uses current window size (500x375 for profile feed)." width="72" />
<button bottom_delta="0" follows="left|top" font="SansSerifSmall" halign="center"
height="20" label="&lt;&lt;Default" left_delta="0"
mouse_opaque="true" name="less_btn" scale_image="TRUE"
tool_tip="Advanced Options. Default uses current window size." width="72" />
tool_tip="Advanced Options. Default uses current window size (500x375 for profile feed)." width="72" />
<slider bottom_delta="0" decimal_digits="0" follows="left|top" height="15"
increment="1" initial_val="75" left="80"
max_val="100" min_val="0" name="image_quality_slider" width="150" />
@@ -69,23 +69,23 @@
<combo_item name="CurrentWindow" value="[i0,i0]">
Current Window
</combo_item>
<combo_item name="640x480" value="[i640,i480]">
640x480
<combo_item name="500x500" value="[i500,i500]">
500x500 (1:1)
</combo_item>
<combo_item name="700x525" value="[i700,i525]">
700x525 (prefered)
<combo_item name="500x375" value="[i500,i375]">
500x375 (4:3)
</combo_item>
<combo_item name="800x600" value="[i800,i600]">
800x600 (resized)
<combo_item name="500x350" value="[i500,i350]">
500x350 (10:7)
</combo_item>
<combo_item name="1024x768" value="[i1024,i768]">
1024x768 (resized)
<combo_item name="500x313" value="[i500,i313]">
500x313 (16:10)
</combo_item>
<combo_item name="1280x960" value="[i1280,i960]">
1280x960 (resized)
<combo_item name="500x281" value="[i500,i281]">
500x281 (16:9)
</combo_item>
<combo_item name="1600x1200" value="[i1600,i1200]">
1600x1200 (resized)
<combo_item name="500x250" value="[i500,i250]">
500x250 (2:1)
</combo_item>
<combo_item name="Custom" value="[i-1,i-1]">
Custom
@@ -114,27 +114,27 @@
</combo_box>
<combo_box bottom_delta="0" follows="left|top" height="20" label="Resolution" left="10"
name="texture_size_combo" width="115">
<combo_item name="128x128" value="[i128,i128]">
128x128 (1:1)
<combo_item name="512x512" value="[i512,i512]">
512x512 (1:1)
</combo_item>
<combo_item name="256x256" value="[i256,i256]">
256x256 (1:1)
</combo_item>
<combo_item name="512x512" value="[i512,i512]">
512x512 (1:1)
</combo_item>
<combo_item name="256x128" value="[i256,i128]">
256x128 (2:1)
<combo_item name="128x128" value="[i128,i128]">
128x128 (1:1)
</combo_item>
<combo_item name="512x256" value="[i512,i256]">
512x256 (2:1)
</combo_item>
<combo_item name="128x256" value="[i128,i256]">
128x256 (1:2)
<combo_item name="256x128" value="[i256,i128]">
256x128 (2:1)
</combo_item>
<combo_item name="256x512" value="[i256,i512]">
256x512 (1:2)
</combo_item>
<combo_item name="128x256" value="[i128,i256]">
128x256 (1:2)
</combo_item>
<combo_item name="512x128" value="[i512,i128]">
512x128 (4:1)
</combo_item>
@@ -187,8 +187,8 @@
</text>
<combo_box bottom_delta="-22" follows="left|top" height="20" label="Aspect" left="10"
name="feed_aspect_combo" width="115">
<combo_item name="4:3" value="1.33333">
4:3
<combo_item name="Default" value="-2">
Default
</combo_item>
<combo_item name="Custom" value="-1">
Custom
@@ -212,7 +212,7 @@
1:1
</combo_item>
<combo_item name="4:3" value="1.33333">
4:3 (profile &amp; feed)
4:3 (profile)
</combo_item>
<combo_item name="10:7" value="1.42857">
10:7
@@ -245,7 +245,7 @@
1:1
</combo_item>
<combo_item name="4:3" value="1.33333">
4:3 (profile &amp; feed)
4:3 (profile)
</combo_item>
<combo_item name="10:7" value="1.42857">
10:7
@@ -269,7 +269,7 @@
<spinner bottom_delta="0" decimal_digits="5" follows="left|top" height="20"
increment="0.01" label="" left="130" max_val="32"
min_val="0.03125" name="aspect_ratio" width="64" allow_text_entry="false"/>
<text bottom_delta="-10" left="196">:1</text>
<text bottom_delta="-20" height="20" left="196" name="aspect_one_label">:1</text>
<text bottom_delta="-20" follows="left|top" height="20" left="15"
name="layer_type_label" width="50">
Capture: