diff --git a/src/add-ons/screen_savers/slideshowsaver/Jamfile b/src/add-ons/screen_savers/slideshowsaver/Jamfile new file mode 100644 index 0000000000..3bc1c7797c --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/Jamfile @@ -0,0 +1,18 @@ +SubDir OBOS_TOP src add-ons screen_savers slideshowsaver ; + +ScreenSaver SlideShowSaver : + # LiveSettings + LiveSetting.cpp + LiveSettings.cpp + + # SlideShowSaver classes + SlideShowSaver.cpp + SlideShowConfigView.cpp ; + +LinkSharedOSLibs SlideShowSaver : be screensaver tracker translation ; + +Package haiku-screensavers-cvs : + SlideShowSaver : + boot home config add-ons screen_savers ; + + diff --git a/src/add-ons/screen_savers/slideshowsaver/LiveSetting.cpp b/src/add-ons/screen_savers/slideshowsaver/LiveSetting.cpp new file mode 100644 index 0000000000..df0a63128f --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/LiveSetting.cpp @@ -0,0 +1,198 @@ +/*****************************************************************************/ +// LiveSetting +// Written by Michael Wilber +// +// LiveSetting.cpp +// +// This class stores the default value for an individual setting and provides +// functions which read and write the setting to BMessages. +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include "LiveSetting.h" + +void +LiveSetting::Init(uint32 id, const char *name, const LiveSettingType dataType) +{ + fId = id; + fName = name; + fDataType = dataType; +} + +LiveSetting::LiveSetting(uint32 id, const char *name, bool val) +{ + Init(id, name, LIVE_SETTING_BOOL); + fBoolVal = val; +} + +LiveSetting::LiveSetting(uint32 id, const char *name, int32 val) +{ + Init(id, name, LIVE_SETTING_INT32); + fInt32Val = val; +} + +LiveSetting::LiveSetting(uint32 id, const char *name, const char *val) +{ + Init(id, name, LIVE_SETTING_STRING); + fCharpVal = val; +} + +bool +LiveSetting::AddReplaceValue(BMessage *msgTo, BMessage *msgFrom /*= NULL*/) const +{ + bool bResult = false; + + switch (fDataType) { + case LIVE_SETTING_BOOL: + { + bool bVal; + if (GetValue(msgFrom, bVal) == true) + return AddReplaceValue(msgTo, bVal); + } + case LIVE_SETTING_INT32: + { + int32 iVal; + if (GetValue(msgFrom, iVal) == true) + return AddReplaceValue(msgTo, iVal); + } + case LIVE_SETTING_STRING: + { + BString str; + if (GetValue(msgFrom, str) == true) + return AddReplaceValue(msgTo, str); + } + default: + break; + } + + return bResult; +} + +bool +LiveSetting::AddReplaceValue(BMessage *msgTo, bool val) const +{ + if (msgTo == NULL) + return false; + + bool bResult = false; + bool dummy; + if (msgTo->FindBool(fName, &dummy) == B_OK) { + if (msgTo->ReplaceBool(fName, val) == B_OK) + bResult = true; + } else { + if (msgTo->AddBool(fName, val) == B_OK) + bResult = true; + } + + return bResult; +} + +bool +LiveSetting::AddReplaceValue(BMessage *msgTo, int32 val) const +{ + if (msgTo == NULL) + return false; + + bool bResult = false; + int32 dummy; + if (msgTo->FindInt32(fName, &dummy) == B_OK) { + if (msgTo->ReplaceInt32(fName, val) == B_OK) + bResult = true; + } else { + if (msgTo->AddInt32(fName, val) == B_OK) + bResult = true; + } + + return bResult; +} + +bool +LiveSetting::AddReplaceValue(BMessage *msgTo, const BString &val) const +{ + if (msgTo == NULL) + return false; + + bool bResult = false; + BString dummy; + if (msgTo->FindString(fName, &dummy) == B_OK) { + if (msgTo->ReplaceString(fName, val) == B_OK) + bResult = true; + } else { + if (msgTo->AddString(fName, val) == B_OK) + bResult = true; + } + + return bResult; +} + +bool +LiveSetting::GetValue(BMessage *msgFrom, bool &val) const +{ + if (fDataType != LIVE_SETTING_BOOL) + return false; + + bool bResult = false; + if (msgFrom == NULL) { + val = fBoolVal; + bResult = true; + + } else if (msgFrom->FindBool(fName, &val) == B_OK) + bResult = true; + + return bResult; +} + +bool +LiveSetting::GetValue(BMessage *msgFrom, int32 &val) const +{ + if (fDataType != LIVE_SETTING_INT32) + return false; + + bool bResult = false; + if (msgFrom == NULL) { + val = fInt32Val; + bResult = true; + + } else if (msgFrom->FindInt32(fName, &val) == B_OK) + bResult = true; + + return bResult; +} + +bool +LiveSetting::GetValue(BMessage *msgFrom, BString &val) const +{ + if (fDataType != LIVE_SETTING_STRING) + return false; + + bool bResult = false; + if (msgFrom == NULL) { + val = fCharpVal; + bResult = true; + + } else if (msgFrom->FindString(fName, &val) == B_OK) + bResult = true; + + return bResult; +} + diff --git a/src/add-ons/screen_savers/slideshowsaver/LiveSetting.h b/src/add-ons/screen_savers/slideshowsaver/LiveSetting.h new file mode 100644 index 0000000000..c7c5745140 --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/LiveSetting.h @@ -0,0 +1,83 @@ +/*****************************************************************************/ +// LiveSetting +// Written by Michael Wilber +// +// LiveSetting.h +// +// This class stores the default value for an individual setting and provides +// functions which read and write the setting to BMessages. +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef LIVE_SETTING_H +#define LIVE_SETTING_H + +#include +#include +#include +#include +#include +#include "LiveSettingsObserver.h" + +class LiveSetting { +public: + LiveSetting(uint32 id, const char *name, bool val); + LiveSetting(uint32 id, const char *name, int32 val); + LiveSetting(uint32 id, const char *name, const char *val); + ~LiveSetting() { } + + uint32 GetId() const { return fId; } + const char *GetName() const { return fName; } + + bool AddReplaceValue(BMessage *msgTo, BMessage *msgFrom = NULL) const; + + bool AddReplaceValue(BMessage *msgTo, bool val) const; + bool AddReplaceValue(BMessage *msgTo, int32 val) const; + bool AddReplaceValue(BMessage *msgTo, const BString &val) const; + + bool GetValue(BMessage *msgFrom, bool &val) const; + bool GetValue(BMessage *msgFrom, int32 &val) const; + bool GetValue(BMessage *msgFrom, BString &val) const; + +private: + enum LiveSettingType { + LIVE_SETTING_BOOL = 0, + LIVE_SETTING_INT32, + LIVE_SETTING_STRING + }; + + void Init(uint32 id, const char *name, const LiveSettingType dataType); + + uint32 fId; + const char *fName; + LiveSettingType fDataType; + union { + bool fBoolVal; + int32 fInt32Val; + const char *fCharpVal; + }; +}; + +#endif // #ifndef LIVE_SETTING_H + + diff --git a/src/add-ons/screen_savers/slideshowsaver/LiveSettings.cpp b/src/add-ons/screen_savers/slideshowsaver/LiveSettings.cpp new file mode 100644 index 0000000000..f876802dc6 --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/LiveSettings.cpp @@ -0,0 +1,479 @@ +/*****************************************************************************/ +// LiveSettings +// Written by Michael Wilber +// +// LiveSettings.cpp +// +// This class manages (saves/loads/locks/unlocks) a collection of BMessage +// based settings. This class allows you to share settings between different +// classes in different threads and receive notifications when the settings +// change. This class makes it easy to share settings between a Translator +// and its config panel or a Screen Saver and its config panel. +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include +#include +#include "LiveSettings.h" + +// --------------------------------------------------------------- +// Constructor +// +// Sets the default settings, location for the settings file +// and sets the reference count to 1 +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +LiveSettings::LiveSettings(const char *settingsFile, + LiveSetting *defaults, int32 defCount) + : fLock("LiveSettings Lock") +{ + if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath)) + fSettingsPath.SetTo("/tmp"); + fSettingsPath.Append(settingsFile); + + fRefCount = 1; + + if (defCount > 0) { + fDefaults = defaults; + fDefCount = defCount; + } else { + fDefaults = NULL; + fDefCount = 0; + } + + // Add Default Settings + // (Used when loading from the settings file or from + // a BMessage fails) + const LiveSetting *defs = fDefaults; + for (int32 i = 0; i < fDefCount; i++) + defs[i].AddReplaceValue(&fSettingsMsg); +} + +// --------------------------------------------------------------- +// Acquire +// +// Returns a pointer to the LiveSettings and increments +// the reference count. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this LiveSettings object +// --------------------------------------------------------------- +LiveSettings * +LiveSettings::Acquire() +{ + LiveSettings *psettings = NULL; + + fLock.Lock(); + fRefCount++; + psettings = this; + fLock.Unlock(); + + return psettings; +} + +// --------------------------------------------------------------- +// Release +// +// Decrements the reference count and deletes the +// LiveSettings if the reference count is zero. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: pointer to this LiveSettings object if +// the reference count is greater than zero, returns NULL +// if the reference count is zero and the LiveSettings +// object has been deleted +// --------------------------------------------------------------- +LiveSettings * +LiveSettings::Release() +{ + LiveSettings *psettings = NULL; + + fLock.Lock(); + fRefCount--; + if (fRefCount > 0) { + psettings = this; + fLock.Unlock(); + } else + delete this; + // delete this object and + // release locks + + return psettings; +} + +// --------------------------------------------------------------- +// Destructor +// +// Does nothing! +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +LiveSettings::~LiveSettings() +{ + fObservers.clear(); +} + +// returns true if observer was added sucessfully, +// false if observer already in the list or error +bool +LiveSettings::AddObserver(LiveSettingsObserver *observer) +{ + fLock.Lock(); + + bool bAdd = true; + ObserverList::iterator I = fObservers.begin(); + while (I != fObservers.end()) { + if (*I == observer) { + bAdd = false; + break; + } + I++; + } + + if (bAdd == true) + fObservers.push_back(observer); + + fLock.Unlock(); + + return bAdd; +} + +// returns true if observer was removed successfully, +// false if observer not found or error +bool +LiveSettings::RemoveObserver(LiveSettingsObserver *observer) +{ + fLock.Lock(); + + bool bRemove = false; + ObserverList::iterator I = fObservers.begin(); + while (I != fObservers.end()) { + if (*I == observer) { + bRemove = true; + break; + } + I++; + } + + if (bRemove == true) + fObservers.erase(I); + + fLock.Unlock(); + + return bRemove; +} + +void +LiveSettings::NotifySettingChanged(uint32 setting) +{ + fLock.Lock(); + ObserverList listCopy = fObservers; + fLock.Unlock(); + + ObserverList::iterator I = listCopy.begin(); + while (I != listCopy.end()) { + (*I)->SettingChanged(setting); + I++; + } +} + +// --------------------------------------------------------------- +// LoadSettings +// +// Loads the settings by reading them from the default +// settings file. +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: B_OK if there were no errors or an error code from +// BFile::SetTo() or BMessage::Unflatten() if there were errors +// --------------------------------------------------------------- +status_t +LiveSettings::LoadSettings() +{ + status_t result; + + fLock.Lock(); + + // Don't try to open the settings file if there are + // no settings that need to be loaded + if (fDefCount > 0) { + BFile settingsFile; + result = settingsFile.SetTo(fSettingsPath.Path(), B_READ_ONLY); + if (result == B_OK) { + BMessage msg; + result = msg.Unflatten(&settingsFile); + if (result == B_OK) + result = LoadSettings(&msg); + } + } else + result = B_OK; + + fLock.Unlock(); + + return result; +} + +// --------------------------------------------------------------- +// LoadSettings +// +// Loads the settings from a BMessage passed to the function. +// +// Preconditions: +// +// Parameters: pmsg pointer to BMessage that contains the +// settings +// +// Postconditions: +// +// Returns: B_BAD_VALUE if pmsg is NULL or invalid options +// have been found, B_OK if there were no +// errors or an error code from BMessage::FindBool() or +// BMessage::ReplaceBool() if there were other errors +// --------------------------------------------------------------- +status_t +LiveSettings::LoadSettings(BMessage *pmsg) +{ + status_t result = B_OK; + + if (pmsg) { + + fLock.Lock(); + + const LiveSetting *defs = fDefaults; + for (int32 i = 0; i < fDefCount; i++) + defs[i].AddReplaceValue(&fSettingsMsg, pmsg); + + fLock.Unlock(); + } + + return result; +} + +// --------------------------------------------------------------- +// SaveSettings +// +// Saves the settings as a flattened BMessage to the default +// settings file +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: B_OK if no errors or an error code from BFile::SetTo() +// or BMessage::Flatten() if there were errors +// --------------------------------------------------------------- +status_t +LiveSettings::SaveSettings() +{ + status_t result; + + fLock.Lock(); + + // Only write out settings file if there are + // actual settings stored by this object + if (fDefCount > 0) { + BFile settingsFile; + result = settingsFile.SetTo(fSettingsPath.Path(), + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + if (result == B_OK) + result = fSettingsMsg.Flatten(&settingsFile); + } else + result = B_OK; + + fLock.Unlock(); + + return result; +} + +// --------------------------------------------------------------- +// GetConfigurationMessage +// +// Saves the current settings to the BMessage passed to the +// function +// +// Preconditions: +// +// Parameters: pmsg pointer to BMessage where the settings +// will be stored +// +// Postconditions: +// +// Returns: B_OK if there were no errors or an error code from +// BMessage::RemoveName() or BMessage::AddBool() if there were +// errors +// --------------------------------------------------------------- +status_t +LiveSettings::GetConfigurationMessage(BMessage *pmsg) +{ + status_t result = B_BAD_VALUE; + + if (pmsg) { + int32 i; + for (i = 0; i < fDefCount; i++) { + result = pmsg->RemoveName(fDefaults[i].GetName()); + if (result != B_OK && result != B_NAME_NOT_FOUND) + break; + } + if (i == fDefCount) { + fLock.Lock(); + result = B_OK; + + BString tempStr; + const LiveSetting *defs = fDefaults; + for (i = 0; i < fDefCount && result >= B_OK; i++) + defs[i].AddReplaceValue(pmsg, &fSettingsMsg); + + fLock.Unlock(); + } + } + + return result; +} + +// --------------------------------------------------------------- +// FindLiveSetting +// +// Returns a pointer to the LiveSetting with the given name +// +// +// Preconditions: +// +// Parameters: name name of the LiveSetting to find +// +// +// Postconditions: +// +// Returns: NULL if the LiveSetting cannot be found, or a pointer +// to the desired LiveSetting if it is found +// --------------------------------------------------------------- +const LiveSetting * +LiveSettings::FindLiveSetting(const char *name) +{ + for (int32 i = 0; i < fDefCount; i++) { + if (!strcmp(fDefaults[i].GetName(), name)) + return fDefaults + i; + } + return NULL; +} + +bool +LiveSettings::SetGetBool(const char *name, bool *pVal /*= NULL*/) +{ + bool bPrevVal = false; + GetValue(name, bPrevVal); + if (pVal != NULL) + SetValue(name, *pVal); + + return bPrevVal; +} + +int32 +LiveSettings::SetGetInt32(const char *name, int32 *pVal /*= NULL*/) +{ + int32 iPrevVal = 0; + GetValue(name, iPrevVal); + if (pVal != NULL) + SetValue(name, *pVal); + + return iPrevVal; +} + +void +LiveSettings::SetString(const char *name, const BString &str) +{ + SetValue(name, str); +} + +void +LiveSettings::GetString(const char *name, BString &str) +{ + GetValue(name, str); +} + +template +bool +LiveSettings::SetValue(const char *name, const T &val) +{ + bool bResult = false, bChanged = false; + fLock.Lock(); + + const LiveSetting *def = FindLiveSetting(name); + if (def) { + bResult = def->AddReplaceValue(&fSettingsMsg, val); + bChanged = true; + } + + fLock.Unlock(); + + if (bChanged == true) + NotifySettingChanged(def->GetId()); + + return bResult; +} + +template +bool +LiveSettings::GetValue(const char *name, T &val) +{ + fLock.Lock(); + + bool bResult = false; + const LiveSetting *def = FindLiveSetting(name); + if (def) + bResult = def->GetValue(&fSettingsMsg, val); + + fLock.Unlock(); + + return bResult; +} diff --git a/src/add-ons/screen_savers/slideshowsaver/LiveSettings.h b/src/add-ons/screen_savers/slideshowsaver/LiveSettings.h new file mode 100644 index 0000000000..3a3dec5b89 --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/LiveSettings.h @@ -0,0 +1,108 @@ +/*****************************************************************************/ +// LiveSettings +// Written by Michael Wilber +// +// LiveSettings.h +// +// This class manages (saves/loads/locks/unlocks) a collection of BMessage +// based settings. This class allows you to share settings between different +// classes in different threads and receive notifications when the settings +// change. This class makes it easy to share settings between a Translator +// and its config panel or a Screen Saver and its config panel. +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef LIVE_SETTINGS_H +#define LIVE_SETTINGS_H + +#include +#include +#include +#include +#include +#include "LiveSettingsObserver.h" +#include "LiveSetting.h" + +class LiveSettings { +public: + LiveSettings(const char *settingsFile, LiveSetting *defaults, + int32 defCount); + + LiveSettings *Acquire(); + // increments the reference count, returns this + LiveSettings *Release(); + // decrements the reference count, deletes this + // when count reaches zero, returns this when + // ref count is greater than zero, NULL when + // ref count is zero + + bool AddObserver(LiveSettingsObserver *observer); + // returns true if observer was added sucessfully, + // false if observer already in the list or error + bool RemoveObserver(LiveSettingsObserver *observer); + // returns true if observer was removed successfully, + // false if observer not found or error + + status_t LoadSettings(); + status_t LoadSettings(BMessage *pmsg); + status_t SaveSettings(); + status_t GetConfigurationMessage(BMessage *pmsg); + + bool SetGetBool(const char *name, bool *pVal = NULL); + int32 SetGetInt32(const char *name, int32 *pVal = NULL); + + void SetString(const char *name, const BString &str); + void GetString(const char *name, BString &str); + +private: + const LiveSetting *FindLiveSetting(const char *name); + ~LiveSettings(); + // private so that Release() must be used + // to delete the object + + void NotifySettingChanged(uint32 setting); + + template + bool GetValue(const char *name, T &val); + + template + bool SetValue(const char *name, const T &val); + + BLocker fLock; + int32 fRefCount; + BPath fSettingsPath; + // where the settings file will be loaded from / + // saved to + + BMessage fSettingsMsg; + // the actual settings + + const LiveSetting *fDefaults; + int32 fDefCount; + + typedef std::vector ObserverList; + ObserverList fObservers; +}; + +#endif // #ifndef LIVE_SETTTINGS_H + diff --git a/src/add-ons/screen_savers/slideshowsaver/LiveSettingsObserver.h b/src/add-ons/screen_savers/slideshowsaver/LiveSettingsObserver.h new file mode 100644 index 0000000000..85c21de74b --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/LiveSettingsObserver.h @@ -0,0 +1,44 @@ +/*****************************************************************************/ +// LiveSettingsObserver +// Written by Michael Wilber +// +// LiveSettingsObserver.h +// +// This class provides an interface for classes that wish to get notification +// messages from changes to a LiveSettings object. +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef LIVE_SETTINGS_OBSERVER_H +#define LIVE_SETTINGS_OBSERVER_H + +class LiveSettingsObserver { +public: + LiveSettingsObserver() { } + virtual ~LiveSettingsObserver() { } + + virtual void SettingChanged(uint32 setting) = 0; +}; + +#endif // #ifndef LIVE_SETTINGS_OBSERVER_H + diff --git a/src/add-ons/screen_savers/slideshowsaver/SlideShowConfigView.cpp b/src/add-ons/screen_savers/slideshowsaver/SlideShowConfigView.cpp new file mode 100644 index 0000000000..a405edab02 --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/SlideShowConfigView.cpp @@ -0,0 +1,321 @@ +/*****************************************************************************/ +// SlideShowConfigView +// Written by Michael Wilber +// +// SlideShowConfigView.cpp +// +// This BView based object displays the SlideShowSaver settings options +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include +#include +#include "SlideShowConfigView.h" + +BMessage * +delay_msg(int32 option) +{ + BMessage *pMsg = new BMessage(CHANGE_DELAY); + pMsg->AddInt32("delay", option); + return pMsg; +} + +// --------------------------------------------------------------- +// Constructor +// +// Sets up the view settings +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SlideShowConfigView::SlideShowConfigView(const BRect &frame, const char *name, + uint32 resize, uint32 flags, LiveSettings *settings) + : BView(frame, name, resize, flags) +{ + fSettings = settings; + + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + BMessage *pMsg; + int32 val; + + // Show Caption checkbox + pMsg = new BMessage(CHANGE_CAPTION); + fShowCaption = new BCheckBox(BRect(10, 45, 180, 62), + "Show Caption", "Show Caption", pMsg); + val = (fSettings->SetGetBool(SAVER_SETTING_CAPTION)) ? 1 : 0; + fShowCaption->SetValue(val); + fShowCaption->SetViewColor(ViewColor()); + AddChild(fShowCaption); + + // Change Border checkbox + pMsg = new BMessage(CHANGE_BORDER); + fShowBorder = new BCheckBox(BRect(10, 70, 180, 87), + "Show Border", "Show Border", pMsg); + val = (fSettings->SetGetBool(SAVER_SETTING_BORDER)) ? 1 : 0; + fShowBorder->SetValue(val); + fShowBorder->SetViewColor(ViewColor()); + AddChild(fShowBorder); + + // Delay Menu + // setup PNG interlace options menu + int32 currentDelay = fSettings->SetGetInt32(SAVER_SETTING_DELAY) / 1000; + fDelayMenu = new BPopUpMenu("Delay Menu"); + struct DelayItem { + const char *name; + int32 delay; + }; + DelayItem items[] = { + {"No Delay", 0}, + {"1 second", 1}, + {"2 seconds", 2}, + {"3 seconds", 3}, + {"4 seconds", 4}, + {"5 seconds", 5}, + {"6 seconds", 6}, + {"7 seconds", 7}, + {"8 seconds", 8}, + {"9 seconds", 9}, + {"10 seconds", 10}, + {"15 seconds", 15}, + {"20 seconds", 20}, + {"30 seconds", 30}, + {"1 minute", 1 * 60}, + {"2 minutes", 2 * 60}, + {"5 minutes", 5 * 60}, + {"10 minutes", 10 * 60}, + {"15 minutes", 15 * 60} + }; + for (uint32 i = 0; i < sizeof(items) / sizeof(DelayItem); i++) { + BMenuItem *menuItem = + new BMenuItem(items[i].name, delay_msg(items[i].delay)); + fDelayMenu->AddItem(menuItem); + if (items[i].delay == currentDelay) + menuItem->SetMarked(true); + } + fDelayMenuField = new BMenuField(BRect(10, 100, 180, 120), + "Delay Menu Field", "Delay:", fDelayMenu); + fDelayMenuField->SetViewColor(ViewColor()); + fDelayMenuField->SetDivider(40); + AddChild(fDelayMenuField); + + // Choose Image Folder button + pMsg = new BMessage(CHOOSE_DIRECTORY); + fChooseFolder = new BButton(BRect(50, 160, 180, 180), + "Choose Folder", "Choose Image Folder...", pMsg); + AddChild(fChooseFolder); + + // Setup choose folder file panel + pMsg = new BMessage(CHANGE_DIRECTORY); + fFilePanel = new BFilePanel(B_OPEN_PANEL, NULL, (const entry_ref *) NULL, + B_DIRECTORY_NODE, false, pMsg, NULL, true, true); + fFilePanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); +} + +// --------------------------------------------------------------- +// Destructor +// +// Releases the translator settings +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +SlideShowConfigView::~SlideShowConfigView() +{ + fSettings->Release(); + + delete fFilePanel; + fFilePanel = NULL; +} + +// --------------------------------------------------------------- +// AllAttached +// +// +// +// Preconditions: +// +// Parameters: +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +SlideShowConfigView::AllAttached() +{ + BMessenger msgr(this); + fShowCaption->SetTarget(msgr); + fShowBorder->SetTarget(msgr); + fChooseFolder->SetTarget(msgr); + fFilePanel->SetTarget(msgr); + + // Set target for menu items + for (int32 i = 0; i < fDelayMenu->CountItems(); i++) { + BMenuItem *item = fDelayMenu->ItemAt(i); + if (item) + item->SetTarget(msgr); + } +} + +// --------------------------------------------------------------- +// MessageReceived +// +// Handles state changes of the RLE setting checkbox +// +// Preconditions: +// +// Parameters: message the actual BMessage that was received +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +SlideShowConfigView::MessageReceived(BMessage *message) +{ + bool bNewVal; + switch (message->what) { + case CHANGE_CAPTION: + if (fShowCaption->Value()) + bNewVal = true; + else + bNewVal = false; + fSettings->SetGetBool(SAVER_SETTING_CAPTION, &bNewVal); + fSettings->SaveSettings(); + break; + + case CHANGE_BORDER: + if (fShowBorder->Value()) + bNewVal = true; + else + bNewVal = false; + fSettings->SetGetBool(SAVER_SETTING_BORDER, &bNewVal); + fSettings->SaveSettings(); + break; + + case CHOOSE_DIRECTORY: + { + BString strDirectory; + fSettings->GetString(SAVER_SETTING_DIRECTORY, strDirectory); + BEntry entry(strDirectory.String()); + if (entry.InitCheck() != B_OK) + return; + entry_ref ref; + if (entry.GetRef(&ref) != B_OK) + return; + fFilePanel->SetPanelDirectory(&ref); + + fFilePanel->Show(); + break; + } + + case CHANGE_DIRECTORY: + { + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + return; + BEntry entry(&ref, true); + if (entry.InitCheck() != B_OK) + return; + BPath path(&entry); + if (path.InitCheck() != B_OK) + return; + BString strDirectory = path.Path(); + + fSettings->SetString(SAVER_SETTING_DIRECTORY, strDirectory); + fSettings->SaveSettings(); + + Invalidate(); + break; + } + + case CHANGE_DELAY: + { + int32 newVal; + if (message->FindInt32("delay", &newVal) == B_OK) { + newVal *= 1000; + fSettings->SetGetInt32(SAVER_SETTING_DELAY, &newVal); + fSettings->SaveSettings(); + } + break; + } + + default: + BView::MessageReceived(message); + break; + } +} + +// --------------------------------------------------------------- +// Draw +// +// Draws information about the SlideShowConfigTranslator to this view. +// +// Preconditions: +// +// Parameters: area, not used +// +// Postconditions: +// +// Returns: +// --------------------------------------------------------------- +void +SlideShowConfigView::Draw(BRect area) +{ + SetFont(be_bold_font); + font_height fh; + GetFontHeight(&fh); + float xbold, ybold; + xbold = fh.descent + 1; + ybold = fh.ascent + fh.descent * 2 + fh.leading; + + char title[] = "SlideShow Screen Saver"; + DrawString(title, BPoint(xbold, ybold)); + + SetFont(be_plain_font); + font_height plainh; + GetFontHeight(&plainh); + float yplain; + yplain = plainh.ascent + plainh.descent * 2 + plainh.leading; + + char writtenby[] = "Written by Michael Wilber"; + DrawString(writtenby, BPoint(xbold, yplain * 1 + ybold)); + + // Draw current folder + BString strFolder; + fSettings->GetString(SAVER_SETTING_DIRECTORY, strFolder); + strFolder.Prepend("Image Folder: "); + DrawString(strFolder.String(), BPoint(10, yplain * 9 + ybold)); +} diff --git a/src/add-ons/screen_savers/slideshowsaver/SlideShowConfigView.h b/src/add-ons/screen_savers/slideshowsaver/SlideShowConfigView.h new file mode 100644 index 0000000000..38f6f7ada7 --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/SlideShowConfigView.h @@ -0,0 +1,83 @@ +/*****************************************************************************/ +// SlideShowConfigView +// Written by Michael Wilber +// +// SlideShowConfigView.h +// +// This BView based object displays the SlideShowSaver settings options +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef SLIDE_SHOW_CONFIG_VIEW_H +#define SLIDE_SHOW_CONFIG_VIEW_H + +#include +#include +#include +#include +#include +#include +#include +#include "LiveSettings.h" + +// SlideShowSaver Settings +enum { + CHANGE_CAPTION, + CHANGE_BORDER, + CHOOSE_DIRECTORY, CHANGE_DIRECTORY, + CHANGE_DELAY +}; +#define SAVER_SETTING_CAPTION "slidesaver /caption" +#define SAVER_SETTING_BORDER "slidesaver /border" +#define SAVER_SETTING_DIRECTORY "slidesaver /directory" +#define SAVER_SETTING_DELAY "slidesaver /delay" + +class SlideShowConfigView : public BView { +public: + SlideShowConfigView(const BRect &frame, const char *name, uint32 resize, + uint32 flags, LiveSettings *settings); + // sets up the view + + ~SlideShowConfigView(); + // releases the settings + + virtual void AllAttached(); + virtual void MessageReceived(BMessage *message); + + virtual void Draw(BRect area); + // draws information about the slide show screen saver +private: + BCheckBox *fShowCaption; + BCheckBox *fShowBorder; + BPopUpMenu *fDelayMenu; + BMenuField *fDelayMenuField; + BButton *fChooseFolder; + + BFilePanel *fFilePanel; + + LiveSettings *fSettings; + // the actual settings for the screen saver, + // shared with the screen saver +}; + +#endif // #ifndef SLIDE_SHOW_CONFIG_VIEW_H diff --git a/src/add-ons/screen_savers/slideshowsaver/SlideShowSaver.cpp b/src/add-ons/screen_savers/slideshowsaver/SlideShowSaver.cpp new file mode 100644 index 0000000000..ef97565a2d --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/SlideShowSaver.cpp @@ -0,0 +1,510 @@ +/*****************************************************************************/ +// SlideShowSaver +// Written by Michael Wilber +// Slide show code derived from ShowImage code, written by Michael Pfeiffer +// +// SlideShowSaver.cpp +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SlideShowSaver.h" +#include "SlideShowConfigView.h" + +// Called by system to get the screen saver +extern "C" _EXPORT BScreenSaver * +instantiate_screen_saver(BMessage *message, image_id id) +{ + return new SlideShowSaver(message, id); +} + +// returns B_ERROR if problems reading ref +// B_OK if ref is not a directory +// B_OK + 1 if ref is a directory +status_t +ent_is_dir(const entry_ref *ref) +{ + BEntry ent(ref); + if (ent.InitCheck() != B_OK) + return B_ERROR; + + struct stat st; + if (ent.GetStat(&st) != B_OK) + return B_ERROR; + + return S_ISDIR(st.st_mode) ? (B_OK + 1) : B_OK; +} + +int CompareEntries(const void* a, const void* b) +{ + entry_ref *r1, *r2; + r1 = *(entry_ref**)a; + r2 = *(entry_ref**)b; + return strcasecmp(r1->name, r2->name); +} + +// Default settings for the Translator +LiveSetting gDefaultSettings[] = { + LiveSetting(CHANGE_CAPTION, SAVER_SETTING_CAPTION, true), + // Show image caption by default + LiveSetting(CHANGE_BORDER, SAVER_SETTING_BORDER, true), + // Show image border by default + LiveSetting(CHANGE_DIRECTORY, SAVER_SETTING_DIRECTORY, "/boot/home"), + // Set default image directory to home + LiveSetting(CHANGE_DELAY, SAVER_SETTING_DELAY, (int32) 3000) + // Default delay: 3 seconds +}; + +SlideShowSaver::SlideShowSaver(BMessage *archive, image_id image) + : BScreenSaver(archive, image), fLock("SlideShow Lock") +{ + fNewDirectory = true; + fBitmap = NULL; + fShowBorder = true; + fShowCaption = true; + + fSettings = new LiveSettings("SlideShowSaver_Settings", + gDefaultSettings, sizeof(gDefaultSettings) / sizeof(LiveSetting)); + fSettings->LoadSettings(); + // load settings from the settings file + + fSettings->AddObserver(this); +} + +SlideShowSaver::~SlideShowSaver() +{ + delete fBitmap; + fBitmap = NULL; + + fSettings->RemoveObserver(this); + fSettings->Release(); +} + +// Called by fSettings to notify that someone has changed +// a setting. For example, if the user changes a setting +// on the config panel, this will be called to notify this +// object. +void +SlideShowSaver::SettingChanged(uint32 setting) +{ + switch (setting) { + case CHANGE_CAPTION: + UpdateShowCaption(); + break; + case CHANGE_BORDER: + UpdateShowBorder(); + break; + case CHANGE_DIRECTORY: + UpdateDirectory(); + break; + case CHANGE_DELAY: + UpdateTickSize(); + break; + + default: + break; + } +} + +status_t +SlideShowSaver::UpdateTickSize() +{ + // Tick size is in microseconds, but is stored in settings as + // milliseconds + bigtime_t ticks = static_cast + (fSettings->SetGetInt32(SAVER_SETTING_DELAY)) * 1000; + SetTickSize(ticks); + + return B_OK; +} + +status_t +SlideShowSaver::UpdateShowCaption() +{ + fShowCaption = fSettings->SetGetBool(SAVER_SETTING_CAPTION); + return B_OK; +} + +status_t +SlideShowSaver::UpdateShowBorder() +{ + fShowBorder = fSettings->SetGetBool(SAVER_SETTING_BORDER); + return B_OK; +} + +status_t +SlideShowSaver::UpdateDirectory() +{ + status_t result = B_OK; + + fLock.Lock(); + + BString strDirectory; + fSettings->GetString(SAVER_SETTING_DIRECTORY, strDirectory); + BDirectory dir(strDirectory.String()); + if (dir.InitCheck() != B_OK || dir.GetNextRef(&fCurrentRef) != B_OK) + result = B_ERROR; + // Use ShowNextImage to find which translatable image is + // alphabetically first in the given directory, and load it + if (result == B_OK && ShowNextImage(true, true) == false) + result = B_ERROR; + + fNewDirectory = true; + + fLock.Unlock(); + + return result; +} + +void +SlideShowSaver::StartConfig(BView *view) +{ + view->AddChild(new SlideShowConfigView( + BRect(10, 10, 250, 300), "SlideShowSaver Config", + B_FOLLOW_ALL, B_WILL_DRAW, fSettings->Acquire())); +} + +status_t +SlideShowSaver::StartSaver(BView *view, bool preview) +{ + UpdateShowCaption(); + UpdateShowBorder(); + + if (UpdateDirectory() != B_OK) + return B_ERROR; + + // Read ticksize setting and set it as the delay + UpdateTickSize(); + + return B_OK; +} + +void +SlideShowSaver::Draw(BView *view, int32 frame) +{ + fLock.Lock(); + + view->SetLowColor(0, 0, 0); + view->SetHighColor(192, 192, 192); + view->SetViewColor(192, 192, 192); + + bool bResult = false; + if (fNewDirectory == true) { + // Already have a bitmap on the first frame + bResult = true; + } else { + bResult = ShowNextImage(true, false); + // try rewinding to beginning + if (bResult == false) + bResult = ShowNextImage(true, true); + } + fNewDirectory = false; + + if (bResult == true && fBitmap != NULL) { + BRect destRect(0, 0, fBitmap->Bounds().Width(), fBitmap->Bounds().Height()), + vwBounds = view->Bounds(); + + if (destRect.Width() < vwBounds.Width()) { + destRect.OffsetBy((vwBounds.Width() - destRect.Width()) / 2, 0); + } + if (destRect.Height() < vwBounds.Height()) { + destRect.OffsetBy(0, (vwBounds.Height() - destRect.Height()) / 2); + } + + BRect border = destRect, bounds = view->Bounds(); + // top + view->FillRect(BRect(0, 0, bounds.right, border.top-1), B_SOLID_LOW); + // left + view->FillRect(BRect(0, border.top, border.left-1, border.bottom), B_SOLID_LOW); + // right + view->FillRect(BRect(border.right+1, border.top, bounds.right, border.bottom), B_SOLID_LOW); + // bottom + view->FillRect(BRect(0, border.bottom+1, bounds.right, bounds.bottom), B_SOLID_LOW); + + if (fShowBorder == true) { + BRect strokeRect = destRect; + strokeRect.InsetBy(-1, -1); + view->StrokeRect(strokeRect); + } + + view->DrawBitmap(fBitmap, fBitmap->Bounds(), destRect); + + if (fShowCaption == true) + DrawCaption(view); + } + + fLock.Unlock(); +} + +status_t +SlideShowSaver::SetImage(const entry_ref *pref) +{ + entry_ref ref; + if (!pref) + ref = fCurrentRef; + else + ref = *pref; + + BTranslatorRoster *proster = BTranslatorRoster::Default(); + if (!proster) + return B_ERROR; + + if (ent_is_dir(pref) != B_OK) + // if ref is erroneous or a directory, return error + return B_ERROR; + + BFile file(&ref, B_READ_ONLY); + translator_info info; + memset(&info, 0, sizeof(translator_info)); + BMessage ioExtension; + //if (ref != fCurrentRef) + // if new image, reset to first document + // fDocumentIndex = 1; + if (ioExtension.AddInt32("/documentIndex", 1 /*fDocumentIndex*/) != B_OK) + return B_ERROR; + if (proster->Identify(&file, &ioExtension, &info, 0, NULL, + B_TRANSLATOR_BITMAP) != B_OK) + return B_ERROR; + + // Translate image data and create a new ShowImage window + BBitmapStream outstream; + if (proster->Translate(&file, &info, &ioExtension, &outstream, + B_TRANSLATOR_BITMAP) != B_OK) + return B_ERROR; + BBitmap *newBitmap = NULL; + if (outstream.DetachBitmap(&newBitmap) != B_OK) + return B_ERROR; + + // Now that I've successfully loaded the new bitmap, + // I can be sure it is safe to delete the old one, + // and clear everything + delete fBitmap; + fBitmap = newBitmap; + newBitmap = NULL; + fCurrentRef = ref; + + // Get path to use in caption + fCaption = "<< Unable to read the path >>"; + BEntry entry(&fCurrentRef); + if (entry.InitCheck() == B_OK) { + BPath path(&entry); + if (path.InitCheck() == B_OK) { + fCaption = path.Path(); + } + } + + return B_OK; +} + +// Function originally from Haiku ShowImage +bool +SlideShowSaver::ShowNextImage(bool next, bool rewind) +{ + bool found; + entry_ref curRef, imgRef; + + curRef = fCurrentRef; + found = FindNextImage(&curRef, &imgRef, next, rewind); + if (found) { + // Keep trying to load images until: + // 1. The image loads successfully + // 2. The last file in the directory is found (for find next or find first) + // 3. The first file in the directory is found (for find prev) + // 4. The call to FindNextImage fails for any other reason + while (SetImage(&imgRef) != B_OK) { + curRef = imgRef; + found = FindNextImage(&curRef, &imgRef, next, false); + if (!found) + return false; + } + return true; + } + return false; +} + +// Function taken from Haiku ShowImage, +// function originally written by Michael Pfeiffer +bool +SlideShowSaver::IsImage(const entry_ref *pref) +{ + if (!pref) + return false; + + if (ent_is_dir(pref) != B_OK) + // if ref is erroneous or a directory, return false + return false; + + BFile file(pref, B_READ_ONLY); + if (file.InitCheck() != B_OK) + return false; + + BTranslatorRoster *proster = BTranslatorRoster::Default(); + if (!proster) + return false; + + BMessage ioExtension; + if (ioExtension.AddInt32("/documentIndex", 1) != B_OK) + return false; + + translator_info info; + memset(&info, 0, sizeof(translator_info)); + if (proster->Identify(&file, &ioExtension, &info, 0, NULL, + B_TRANSLATOR_BITMAP) != B_OK) + return false; + + return true; +} + +// Function taken from Haiku ShowImage, +// function originally written by Michael Pfeiffer +bool +SlideShowSaver::FindNextImage(entry_ref *in_current, entry_ref *out_image, bool next, bool rewind) +{ +// ASSERT(next || !rewind); + BEntry curImage(in_current); + entry_ref entry, *ref; + BDirectory parent; + BList entries; + bool found = false; + int32 cur; + + if (curImage.GetParent(&parent) != B_OK) + return false; + + while (parent.GetNextRef(&entry) == B_OK) { + if (entry != *in_current) { + entries.AddItem(new entry_ref(entry)); + } else { + // insert current ref, so we can find it easily after sorting + entries.AddItem(in_current); + } + } + + entries.SortItems(CompareEntries); + + cur = entries.IndexOf(in_current); +// ASSERT(cur >= 0); + + // remove it so FreeEntries() does not delete it + entries.RemoveItem(in_current); + + if (next) { + // find the next image in the list + if (rewind) cur = 0; // start with first + for (; (ref = (entry_ref*)entries.ItemAt(cur)) != NULL; cur ++) { + if (IsImage(ref)) { + found = true; + *out_image = (const entry_ref)*ref; + break; + } + } + } else { + // find the previous image in the list + cur --; + for (; cur >= 0; cur --) { + ref = (entry_ref*)entries.ItemAt(cur); + if (IsImage(ref)) { + found = true; + *out_image = (const entry_ref)*ref; + break; + } + } + } + + FreeEntries(&entries); + return found; +} + +// Function taken from Haiku ShowImage, +// function originally written by Michael Pfeiffer +void +SlideShowSaver::FreeEntries(BList *entries) +{ + const int32 n = entries->CountItems(); + for (int32 i = 0; i < n; i ++) { + entry_ref *ref = (entry_ref *)entries->ItemAt(i); + delete ref; + } + entries->MakeEmpty(); +} + +void +SlideShowSaver::LayoutCaption(BView *view, BFont &font, BPoint &pos, BRect &rect) +{ + font_height fontHeight; + float width, height; + BRect bounds(view->Bounds()); + font = be_plain_font; + width = font.StringWidth(fCaption.String()) + 1; // 1 for text shadow + font.GetHeight(&fontHeight); + height = fontHeight.ascent + fontHeight.descent; + // center text horizontally + pos.x = (bounds.left + bounds.right - width)/2; + // flush bottom + pos.y = bounds.bottom - fontHeight.descent - 5; + + // background rectangle + rect.Set(0, 0, (width-1)+2, (height-1)+2+1); // 2 for border and 1 for text shadow + rect.OffsetTo(pos); + rect.OffsetBy(-1, -1-fontHeight.ascent); // -1 for border +} + +void +SlideShowSaver::DrawCaption(BView *view) +{ + BFont font; + BPoint pos; + BRect rect; + LayoutCaption(view, font, pos, rect); + + view->PushState(); + // draw background + view->SetDrawingMode(B_OP_ALPHA); + view->SetHighColor(0, 0, 255, 128); + view->FillRect(rect); + // draw text + view->SetDrawingMode(B_OP_OVER); + view->SetFont(&font); + view->SetLowColor(B_TRANSPARENT_COLOR); + // text shadow + pos += BPoint(1, 1); + view->SetHighColor(0, 0, 0); + view->SetPenSize(1); + view->DrawString(fCaption.String(), pos); + // text + pos -= BPoint(1, 1); + view->SetHighColor(255, 255, 0); + view->DrawString(fCaption.String(), pos); + view->PopState(); +} + + diff --git a/src/add-ons/screen_savers/slideshowsaver/SlideShowSaver.h b/src/add-ons/screen_savers/slideshowsaver/SlideShowSaver.h new file mode 100644 index 0000000000..6ee3e65fa1 --- /dev/null +++ b/src/add-ons/screen_savers/slideshowsaver/SlideShowSaver.h @@ -0,0 +1,98 @@ +/*****************************************************************************/ +// SlideShowSaver +// Written by Michael Wilber +// Slide show code derived from ShowImage code, written by Michael Pfeiffer +// +// SlideShowSaver.h +// +// +// Copyright (C) Haiku +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + + +#ifndef SLIDE_SHOW_SAVER_H +#define SLIDE_SHOW_SAVER_H + +#include +#include +#include +#include +#include +#include "LiveSettings.h" + +class SlideShowSaver : + public BScreenSaver, + public LiveSettingsObserver { +public: + SlideShowSaver(BMessage *archive, image_id image); + virtual ~SlideShowSaver(void); + + virtual void SettingChanged(uint32 setting); + + virtual void StartConfig(BView *view); + virtual status_t StartSaver(BView *view, bool preview); + virtual void Draw(BView *view, int32 frame); + +protected: + // reload ticksize setting and apply it + status_t UpdateTickSize(); + + status_t UpdateShowCaption(); + status_t UpdateShowBorder(); + // reload directory setting and apply it + status_t UpdateDirectory(); + + // Function taken from Haiku ShowImage, + // function originally written by Michael Pfeiffer + status_t SetImage(const entry_ref *pref); + + // Function originally from Haiku ShowImage + bool ShowNextImage(bool next, bool rewind); + + // Function taken from Haiku ShowImage, + // function originally written by Michael Pfeiffer + bool IsImage(const entry_ref *pref); + + // Function taken from Haiku ShowImage, + // function originally written by Michael Pfeiffer + bool FindNextImage(entry_ref *in_current, entry_ref *out_image, bool next, bool rewind); + + // Function taken from Haiku ShowImage, + // function originally written by Michael Pfeiffer + void SlideShowSaver::FreeEntries(BList *entries); + + void LayoutCaption(BView *view, BFont &font, BPoint &pos, BRect &rect); + void DrawCaption(BView *view); + // void UpdateCaption(BView *view); + +private: + BLocker fLock; + bool fNewDirectory; + LiveSettings *fSettings; + BBitmap *fBitmap; + BString fCaption; + entry_ref fCurrentRef; + bool fShowCaption; + bool fShowBorder; +}; + +#endif // #ifndef SLIDE_SHOW_SAVER_H +