Add support for flushing messages from plugin to viewer.

Actually flush messages before terminating a plugin (upon
the shutdown message) and flush messages in the file- and
dirpicker before opening the blocking dialog. Flush debug
messages too (deeper into the code, just prior to the actual
blocking call).

Also, fix the context folder map to be a thread-safe
singleton and *attempt* to add support for default folders
to windows and Mac. The latter might even not compile yet
and definitely have to be tested (and fixed):
Opening a DirPicker in preferences --> Network and Set
the directory location of the cache. It should open a
Dialog window where you are already in the folder that
is the current cache directory setting (you can click
Cancel after verifying that this worked).
And, start to upload an image, select a file is some
directory (other than what it starts in). You can omit
the actual upload by clicking cancel in the preview.
Then upload again and now it should start in the same
folder as that you were just in. Possibly you need to
first open a file picker elsewhere with a different context
though, or windows might choose to open in the last
folder anyway while the code doesn't really work. Uploading
a sound before the second texture upload should do the
trick.
This commit is contained in:
Aleric Inglewood
2011-05-12 18:22:51 +02:00
parent 38b33328e6
commit 5f72cbb103
15 changed files with 258 additions and 91 deletions

View File

@@ -115,6 +115,20 @@ void BasicPluginBase::sendLogMessage(std::string const& message, LLPluginMessage
logmessage.setValue("message", message);
logmessage.setValueS32("log_level",level);
mSendMessageFunction(logmessage.generate().c_str(), &mPluginInstance);
// Theoretically we should flush here (that's what PLS_ENDL means), but we don't because
// that interfers with how the code would act without debug messages. Instead, the developer
// is responsible to call flushMessages themselves at the appropriate places.
}
/**
* Flush all messages to the viewer.
*
* This blocks if necessary, up till 10 seconds, before it gives up.
*/
void BasicPluginBase::flushMessages(void)
{
LLPluginMessage logmessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "flush");
mSendMessageFunction(logmessage.generate().c_str(), &mPluginInstance);
}
/**
@@ -124,6 +138,9 @@ void BasicPluginBase::sendLogMessage(std::string const& message, LLPluginMessage
*/
void BasicPluginBase::sendShutdownMessage(void)
{
// Do a double flush. First flush all messages so far, then send the shutdown message,
// which also will try to flush itself before terminating the process.
flushMessages();
LLPluginMessage shutdownmessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shutdown");
sendMessage(shutdownmessage);
}

View File

@@ -36,16 +36,13 @@
#ifndef BASIC_PLUGIN_BASE_H
#define BASIC_PLUGIN_BASE_H
#include <sstream>
#include <sstream>
#include "linden_common.h"
#include "llplugininstance.h"
#include "llpluginmessage.h"
#include "llpluginmessageclasses.h"
#include <sstream>
class BasicPluginBase
{
public:
@@ -65,7 +62,10 @@ public:
// Used for log messages. Use macros below.
void sendLogMessage(std::string const& message, LLPluginMessage::LLPLUGIN_LOG_LEVEL level);
// Shoot down the whole process.
// Flush all messages to the viewer.
void flushMessages(void);
// Flush all messages and then shoot down the whole process.
void sendShutdownMessage(void);
protected:
@@ -127,6 +127,7 @@ int create_plugin(
#define PLS_INFOS PLS_LOG_MESSAGE(LLPluginMessage::LOG_LEVEL_INFO, LL_DEBUG_PLUGIN_MESSAGES)
#define PLS_WARNS PLS_LOG_MESSAGE(LLPluginMessage::LOG_LEVEL_WARN, 1)
#define PLS_ERRS PLS_LOG_MESSAGE(LLPluginMessage::LOG_LEVEL_ERR, 1)
#define PLS_FLUSH do { BasicPluginBase::sPluginBase->flushMessages(); } while(0)
#endif // BASIC_PLUGIN_BASE

View File

@@ -232,10 +232,13 @@ void FilepickerPlugin::receiveMessage(char const* message_string)
std::string folder = message_in.getValue("folder");
bool get_directory = (filter == "directory");
// We about to completely block on running the modal File/Dir picker window, so flush any pending messages to the viewer.
flushMessages();
bool canceled;
if (get_directory)
{
canceled = !LLDirPicker::instance().getDir(&folder);
canceled = !LLDirPicker::instance().getDir(folder);
}
else if (type == "save")
{
@@ -275,6 +278,7 @@ void FilepickerPlugin::receiveMessage(char const* message_string)
sendMessage(message);
}
// We're done. Exit the whole application.
// This first flushes any messages before terminating the plugin.
sendShutdownMessage();
}
else

View File

@@ -28,8 +28,8 @@
* - Initial version, written by Aleric Inglewood @ SL
*/
#include "legacy.h"
#include "basic_plugin_base.h" // For PLS_INFOS etc.
#include "legacy.h"
// Translation map.
translation_map_type translation_map;

View File

@@ -65,7 +65,15 @@ LLDirPicker::~LLDirPicker()
// nothing
}
BOOL LLDirPicker::getDir(std::string* filename)
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if (uMsg == BFFM_INITIALIZED)
{
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
}
}
BOOL LLDirPicker::getDir(std::string const& folder)
{
if( mLocked )
{
@@ -73,34 +81,38 @@ BOOL LLDirPicker::getDir(std::string* filename)
}
BOOL success = FALSE;
BROWSEINFO bi;
memset(&bi, 0, sizeof(bi));
BROWSEINFO bi;
memset(&bi, 0, sizeof(bi));
bi.ulFlags = BIF_USENEWUI;
bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
bi.lpszTitle = NULL;
bi.ulFlags = BIF_USENEWUI;
bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
bi.lpszTitle = NULL;
llutf16string tstring = utf8str_to_utf16str(folder);
bi.lParam = (LPARAM)tstring.c_str();
bi.lpfn = &BrowseCallbackProc;
::OleInitialize(NULL);
::OleInitialize(NULL);
LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
PLS_FLUSH;
LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
if(pIDL != NULL)
{
WCHAR buffer[_MAX_PATH] = {'\0'};
if(pIDL != NULL)
{
WCHAR buffer[_MAX_PATH] = {'\0'};
if(::SHGetPathFromIDList(pIDL, buffer) != 0)
{
// Set the string value.
if(::SHGetPathFromIDList(pIDL, buffer) != 0)
{
// Set the string value.
mDir = utf16str_to_utf8str(llutf16string(buffer));
success = TRUE;
}
mDir = utf16str_to_utf8str(llutf16string(buffer));
success = TRUE;
}
// free the item id list
CoTaskMemFree(pIDL);
}
// free the item id list
CoTaskMemFree(pIDL);
}
::OleUninitialize();
::OleUninitialize();
return success;
}
@@ -147,9 +159,9 @@ pascal void LLDirPicker::doNavCallbackEvent(NavEventCallbackMessage callBackSele
//Convert string to a FSSpec
FSRef myFSRef;
const char* filename=sInstance.mFileName->c_str();
const char* folder = sInstance.mFileName->c_str();
error = FSPathMakeRef ((UInt8*)filename, &myFSRef, NULL);
error = FSPathMakeRef ((UInt8*)folder, &myFSRef, NULL);
if (error != noErr) break;
@@ -185,7 +197,10 @@ OSStatus LLDirPicker::doNavChooseDialog()
gViewerWindow->mWindow->beforeDialog();
if (error == noErr)
{
PLS_FLUSH;
error = NavDialogRun(navRef);
}
gViewerWindow->mWindow->afterDialog();
@@ -216,13 +231,13 @@ OSStatus LLDirPicker::doNavChooseDialog()
return error;
}
BOOL LLDirPicker::getDir(std::string* filename)
BOOL LLDirPicker::getDir(std::string const& folder)
{
if( mLocked ) return FALSE;
BOOL success = FALSE;
OSStatus error = noErr;
mFileName = filename;
mFileName = folder;
// mNavOptions.saveFileName
@@ -266,14 +281,15 @@ void LLDirPicker::reset()
LLFilePickerBase::reset();
}
BOOL LLDirPicker::getDir(std::string* filename)
BOOL LLDirPicker::getDir(std::string const& folder)
{
reset();
GtkWindow* picker = buildFilePicker(false, true, "dirpicker");
GtkWindow* picker = buildFilePicker(false, true, folder);
if (picker)
{
gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("choose_the_directory").c_str());
gtk_widget_show_all(GTK_WIDGET(picker));
PLS_FLUSH;
gtk_main();
return (!getFirstFile().empty());
}
@@ -301,7 +317,7 @@ void LLDirPicker::reset()
{
}
BOOL LLDirPicker::getDir(std::string* filename)
BOOL LLDirPicker::getDir(std::string* folder)
{
return FALSE;
}

View File

@@ -71,7 +71,7 @@ public:
// calling this before main() is undefined
static LLDirPicker& instance( void ) { return sInstance; }
BOOL getDir(std::string* filename);
BOOL getDir(std::string const& filename);
std::string getDirName();
// clear any lists of buffers or whatever, and make sure the dir

View File

@@ -205,7 +205,6 @@ bool LLFilePickerBase::setupFilter(ELoadFilter filter)
return res;
}
// AIFIXME: Use folder
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
@@ -214,9 +213,9 @@ bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder
}
bool success = FALSE;
// don't provide default file selection
llutf16string tstring = utf8str_to_utf16str(folder);
mOFN.lpstrInitialDir = (LPCTSTR)tstring.data();
mFilesW[0] = '\0';
mOFN.lpstrFile = mFilesW;
mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ;
@@ -237,7 +236,6 @@ bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder
return success;
}
// AIFIXME: Use folder
bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
@@ -246,9 +244,9 @@ bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string cons
}
bool success = FALSE;
// don't provide default file selection
llutf16string tstring = utf8str_to_utf16str(folder);
mOFN.lpstrInitialDir = (LPCTSTR)tstring.data();
mFilesW[0] = '\0';
mOFN.lpstrFile = mFilesW;
mOFN.nFilterIndex = 1;
mOFN.nMaxFile = FILENAME_BUFFER_SIZE;
@@ -295,7 +293,6 @@ bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string cons
return success;
}
// AIFIXME: Use folder
bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
if( mLocked )
@@ -304,11 +301,13 @@ bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filena
}
bool success = FALSE;
llutf16string tstring = utf8str_to_utf16str(folder);
mOFN.lpstrInitialDir = (LPCTSTR)tstring.data();
mOFN.lpstrFile = mFilesW;
if (!filename.empty())
{
llutf16string tstring = utf8str_to_utf16str(filename);
wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/
wcsncpy(mFilesW, tstring.data(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/
else
{
mFilesW[0] = '\0';
@@ -705,8 +704,9 @@ bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filena
Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
{
LLFilePickerBase* picker = (LLFilePickerBase*)callBackUD;
Boolean result = true;
ELoadFilter filter = *((ELoadFilter*) callBackUD);
ELoadFilter filter = picker->getLoadFilter();
OSStatus error = noErr;
if (filterMode == kNavFilteringBrowserList && filter != FFLOAD_ALL && (theItem->descriptorType == typeFSRef || theItem->descriptorType == typeFSS))
@@ -788,7 +788,7 @@ Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *c
}
else if (filter == FFLOAD_RAW)
{
if (fileInfo.filetype != '\?\?\?\?' &&
if (fileInfo.filetype != L'\?\?\?\?' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("raw"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
@@ -809,23 +809,70 @@ Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *c
return result;
}
OSStatus LLFilePickerBase::doNavChooseDialog(ELoadFilter filter)
//static
pascal void LLFilePickerBase::doNavCallbackEvent(NavEventCallbackMessage callBackSelector,
NavCBRecPtr callBackParms, void* callBackUD)
{
switch(callBackSelector)
{
case kNavCBStart:
{
LLFilePickerBase* picker = reinterpret_cast<LLFilePickerBase*>(callBackUD);
if (picker->getFolder().empty()) break;
OSStatus error = noErr;
AEDesc theLocation = {typeNull, NULL};
FSSpec outFSSpec;
//Convert string to a FSSpec
FSRef myFSRef;
const char* folder = picker->getFolder().c_str();
error = FSPathMakeRef ((UInt8*)folder, &myFSRef, NULL);
if (error != noErr) break;
error = FSGetCatalogInfo (&myFSRef, kFSCatInfoNone, NULL, NULL, &outFSSpec, NULL);
if (error != noErr) break;
error = AECreateDesc(typeFSS, &outFSSpec, sizeof(FSSpec), &theLocation);
if (error != noErr) break;
error = NavCustomControl(callBackParms->context,
kNavCtlSetLocation, (void*)&theLocation);
}
}
}
OSStatus LLFilePickerBase::doNavChooseDialog(ELoadFilter filter, std::string const& folder)
{
OSStatus error = noErr;
NavDialogRef navRef = NULL;
NavReplyRecord navReply;
memset(&navReply, 0, sizeof(navReply));
mLoadFilter = filter;
mFolder = folder;
NavEventUPP eventProc = NewNavEventUPP(doNavCallbackEvent);
// NOTE: we are passing the address of a local variable here.
// This is fine, because the object this call creates will exist for less than the lifetime of this function.
// (It is destroyed by NavDialogDispose() below.)
error = NavCreateChooseFileDialog(&mNavOptions, NULL, NULL, NULL, navOpenFilterProc, (void*)(&filter), &navRef);
error = NavCreateChooseFileDialog(&mNavOptions, NULL, eventProc, NULL, navOpenFilterProc, (void*)this, &navRef);
//gViewerWindow->mWindow->beforeDialog();
if (error == noErr)
{
PLS_FLUSH;
error = NavDialogRun(navRef);
}
//gViewerWindow->mWindow->afterDialog();
@@ -860,11 +907,14 @@ OSStatus LLFilePickerBase::doNavChooseDialog(ELoadFilter filter)
mFiles.push_back(std::string(path));
}
}
if (eventProc)
DisposeNavEventUPP(eventProc);
return error;
}
OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
OSStatus error = noErr;
NavDialogRef navRef = NULL;
@@ -905,46 +955,49 @@ OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, const std::string
extension = CFSTR(".png");
break;
case FFSAVE_AVI:
type = '\?\?\?\?';
creator = '\?\?\?\?';
type = L'\?\?\?\?';
creator = L'\?\?\?\?';
extension = CFSTR(".mov");
break;
case FFSAVE_ANIM:
type = '\?\?\?\?';
creator = '\?\?\?\?';
type = L'\?\?\?\?';
creator = L'\?\?\?\?';
extension = CFSTR(".xaf");
break;
#ifdef _CORY_TESTING
case FFSAVE_GEOMETRY:
type = '\?\?\?\?';
creator = '\?\?\?\?';
type = L'\?\?\?\?';
creator = L'\?\?\?\?';
extension = CFSTR(".slg");
break;
#endif
case FFSAVE_RAW:
type = '\?\?\?\?';
creator = '\?\?\?\?';
type = L'\?\?\?\?';
creator = L'\?\?\?\?';
extension = CFSTR(".raw");
break;
case FFSAVE_J2C:
type = '\?\?\?\?';
type = L'\?\?\?\?';
creator = 'prvw';
extension = CFSTR(".j2c");
break;
case FFSAVE_ALL:
default:
type = '\?\?\?\?';
creator = '\?\?\?\?';
type = L'\?\?\?\?';
creator = L'\?\?\?\?';
extension = CFSTR("");
break;
}
NavEventUPP eventUPP = NewNavEventUPP(navSetDefaultFolderProc);
mFolder = folder;
// Create the dialog
error = NavCreatePutFileDialog(&mNavOptions, type, creator, NULL, NULL, &navRef);
error = NavCreatePutFileDialog(&mNavOptions, type, creator, eventUPP, (void*)this, &navRef);
if (error == noErr)
{
CFStringRef nameString = NULL;
@@ -981,7 +1034,10 @@ OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, const std::string
// Run the dialog
if (error == noErr)
{
PLS_FLUSH;
error = NavDialogRun(navRef);
}
//gViewerWindow->mWindow->afterDialog();
@@ -1033,10 +1089,12 @@ OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, const std::string
}
}
if (eventUPP)
DisposeNavEventUPP(eventUPP);
return error;
}
// AIFIXME: Use folder
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
@@ -1050,7 +1108,7 @@ bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
{
error = doNavChooseDialog(filter);
error = doNavChooseDialog(filter, folder);
}
if (error == noErr)
{
@@ -1061,7 +1119,6 @@ bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder
return success;
}
// AIFIXME: Use folder
bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
@@ -1075,7 +1132,7 @@ bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string cons
mNavOptions.optionFlags |= kNavAllowMultipleFiles;
{
error = doNavChooseDialog(filter);
error = doNavChooseDialog(filter, folder);
}
if (error == noErr)
{
@@ -1088,7 +1145,6 @@ bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string cons
return success;
}
// AIFIXME: Use folder
bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
if( mLocked )
@@ -1101,7 +1157,7 @@ bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filena
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
{
error = doNavSaveDialog(filter, filename);
error = doNavSaveDialog(filter, filename, folder);
}
if (error == noErr)
{
@@ -1203,6 +1259,7 @@ GtkWindow* LLFilePickerBase::buildFilePicker(bool is_save, bool is_folder, std::
if (!folder.empty())
{
PLS_DEBUGS << "Calling gtk_file_chooser_set_current_folder(\"" << folder << "\")." << PLS_ENDL;
gtk_file_chooser_set_current_folder
(GTK_FILE_CHOOSER(win),
folder.c_str());
@@ -1225,6 +1282,7 @@ GtkWindow* LLFilePickerBase::buildFilePicker(bool is_save, bool is_folder, std::
G_CALLBACK(LLFilePickerBase::chooser_responder),
this);
PLS_FLUSH;
gtk_window_set_modal(GTK_WINDOW(win), TRUE);
/* GTK 2.6: if (is_folder)
@@ -1383,6 +1441,7 @@ bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filena
}
gtk_widget_show_all(GTK_WIDGET(picker));
PLS_FLUSH;
gtk_main();
rtn = (getFileCount() == 1);
@@ -1430,6 +1489,7 @@ bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder
gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
gtk_widget_show_all(GTK_WIDGET(picker));
PLS_FLUSH;
gtk_main();
rtn = (getFileCount() == 1);
@@ -1458,6 +1518,7 @@ bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string cons
gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str());
gtk_widget_show_all(GTK_WIDGET(picker));
PLS_FLUSH;
gtk_main();
rtn = !mFiles.empty();
}
@@ -1485,7 +1546,6 @@ bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filena
return FALSE;
}
// AIFIXME: Use folder
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
reset();

View File

@@ -166,6 +166,9 @@ private:
OSStatus doNavChooseDialog(ELoadFilter filter);
OSStatus doNavSaveDialog(ESaveFilter filter, const std::string& filename);
static Boolean navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode);
static pascal void LLFilePickerBase::doNavCallbackEvent(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void* callBackUD);
ELoadFilter getLoadFilter(void) const { return mLoadFilter; }
std::string const& getFolder(void) const { return mFolder; }
#endif // LL_DARWIN
#if LL_GTK
@@ -194,7 +197,11 @@ private:
S32 mCurrentFile;
bool mLocked;
bool mMultiFile;
#if LL_DARWIN
ELoadFilter mLoadFilter;
std::string mFolder;
#endif
protected:
#if LL_GTK
GtkWindow* buildFilePicker(bool is_save, bool is_folder, std::string const& folder);