vfesession.h
1 /******************************************************************************* 2 * vfesession.h 3 * 4 * This file contains declarations relating to the vfe session management class. 5 * 6 * Author: Christopher J. Cason 7 * 8 * --------------------------------------------------------------------------- 9 * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7. 10 * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd. 11 * 12 * POV-Ray is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU Affero General Public License as 14 * published by the Free Software Foundation, either version 3 of the 15 * License, or (at your option) any later version. 16 * 17 * POV-Ray is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU Affero General Public License for more details. 21 * 22 * You should have received a copy of the GNU Affero General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * --------------------------------------------------------------------------- 25 * POV-Ray is based on the popular DKB raytracer version 2.12. 26 * DKBTrace was originally written by David K. Buck. 27 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. 28 * --------------------------------------------------------------------------- 29 * $File: //depot/public/povray/3.x/vfe/vfesession.h $ 30 * $Revision: #1 $ 31 * $Change: 6069 $ 32 * $DateTime: 2013/11/06 11:59:40 $ 33 * $Author: chrisc $ 34 *******************************************************************************/ 35 36 #ifndef __VFESESSION_H__ 37 #define __VFESESSION_H__ 38 39 #include <queue> 40 41 #include "base/image/colourspace.h" 42 43 namespace vfe 44 { 45 using namespace pov_frontend; 46 using namespace pov_base; 47 48 //////////////////////////////////////////////////////////////////////////// 49 // class IOPath 50 // 51 // IOPaths are used to keep track of IO Restrictions. Each instance of the 52 // class will contain information regarding a path and its attributes (e.g. 53 // if it's recursive or not). The class by itself doesn't identify if the 54 // path is a permitted or excluded one - this is determined by the collection 55 // to which the instance belongs. 56 class IOPath 57 { 58 public: 59 // construct an IOPath given an existing Path and a recursion flag. 60 IOPath(const Path& path, bool recursive) : m_Path(path), m_Recursive(recursive) {} 61 62 // construct an IOPath given a std::string path and a recursion flag. 63 IOPath(const string& path, bool recursive) : m_Path(Path(ASCIItoUCS2String(path.c_str()))), m_Recursive(recursive) {} 64 65 // construct an IOPath given a UCS2String Path and a recursion flag. 66 IOPath(const UCS2String& path, bool recursive) : m_Path(path), m_Recursive(recursive) {} 67 virtual ~IOPath() {} 68 69 // returns true if paths below the given path are considered to be included 70 // in consideration of an IO restriction. 71 bool IsRecursive() const { return m_Recursive; } 72 73 // return the stored path as an instance of the pov_base::Path class. 74 const Path& GetPath() const { return m_Path; } 75 76 private: 77 bool m_Recursive; 78 Path m_Path; 79 } ; 80 81 // convenience typedefs. 82 typedef vector<string> StringVector; 83 typedef vector<UCS2String> UCS2StringVector; 84 typedef vector<IOPath> IOPathVector; 85 86 class vfeDisplay; 87 class VirtualFrontEnd; 88 89 //////////////////////////////////////////////////////////////////////////// 90 // class vfeDestInfo 91 // 92 // Currently unused, destined to hold information regarding the destination 93 // of a remote session attempt. 94 class vfeDestInfo 95 { 96 } ; 97 98 //////////////////////////////////////////////////////////////////////////// 99 // class vfeAuthInfo 100 // 101 // Currently unused, destined to hold information regarding authentication 102 // when making a remote session open request. 103 class vfeAuthInfo 104 { 105 } ; 106 107 //////////////////////////////////////////////////////////////////////////// 108 // class vfeRenderOptions 109 // 110 // This class is used to hold information regarding a pending render request. 111 // For example, the library paths, source file, output file, and really 112 // anything else that could vary from render to render. 113 class vfeRenderOptions 114 { 115 friend class vfeSession; 116 117 public: 118 // Construct an instance of vfeRenderOptions. the thread count defaults 119 // to 2. 120 vfeRenderOptions() : m_ThreadCount(2) {} 121 virtual ~vfeRenderOptions() {} 122 123 // Clear the set options. This includes library paths, INI files, 124 // commands, the source file, the thread count (defaults back to 2), 125 // and all other options set in the kPOVObjectClass_RenderOptions object. 126 void Clear() 127 { 128 ClearLibraryPaths(); 129 ClearINIs(); 130 ClearCommands(); 131 m_SourceFile.clear(); 132 m_ThreadCount = 2; 133 POVMSObject obj; 134 POVMSObject_New (&obj, kPOVObjectClass_RenderOptions); 135 m_Options = POVMS_Object(obj); 136 } 137 138 // Clear any library paths that have been added. 139 void ClearLibraryPaths() { m_LibraryPaths.clear(); } 140 141 // Add a library path given a std::string. 142 void AddLibraryPath(const string& Path) { m_LibraryPaths.push_back(ASCIItoUCS2String(Path.c_str())); } 143 144 // Add a library path given a UCS2String. 145 void AddLibraryPath(const UCS2String& Path) { m_LibraryPaths.push_back(Path); } 146 147 // Get the current library paths as a vector of UCS2 strings. 148 // The returned paths are a const reference. 149 const UCS2StringVector& GetLibraryPaths() const { return m_LibraryPaths; } 150 151 // Get the current library paths as a vector of UCS2 strings. 152 // The returned paths are a copy of the internal paths. 153 UCS2StringVector GetLibraryPaths() { return m_LibraryPaths; } 154 155 // Set the source file to be parsed (must be an SDL file, INI not 156 // permitted). The file is specified as a UCS2String full or relative 157 // path, with optional extension. 158 void SetSourceFile(const UCS2String& File) { m_SourceFile = File; } 159 160 // Set the source file to be parsed (must be an SDL file, INI not 161 // permitted). The file is specified as a std::string full or relative 162 // path, with optional extension. 163 void SetSourceFile(const string& File) { m_SourceFile = ASCIItoUCS2String(File.c_str()); } 164 165 // Returns a const reference to the currently set source file (may be 166 // an empty string). Return type is a const reference to a UCS2String. 167 const UCS2String& GetSourceFile() const { return m_SourceFile; } 168 169 // Clears the list of INI files. 170 void ClearINIs() { m_IniFiles.clear() ; } 171 172 // Adds the supplied std::string to the list of INI files to be read 173 // prior to the start of the render. The files are processed in the 174 // order in which they are added to this list. 175 void AddINI(const string& File) { m_IniFiles.push_back(ASCIItoUCS2String(File.c_str())); } 176 177 // Adds the supplied UCS2String to the list of INI files to be read 178 // prior to the start of the render. The files are processed in the 179 // order in which they are added to this list. 180 void AddINI(const UCS2String& File) { m_IniFiles.push_back(File); } 181 182 // Returns a const UCS2StringVector reference containing the 183 // list of INI files to be processed, in order first to last. 184 const UCS2StringVector& GetINIs() const { return m_IniFiles; } 185 186 // Returns a UCS2StringVector copy of the list of INI files to be 187 // processed, in order first to last. 188 UCS2StringVector GetINIs() { return m_IniFiles; } 189 190 // Sets the number of threads to be used for rendering (and potentially 191 // for bounding and similar tasks, if this is supported in the future). 192 // Clipped to the range 1..512. 193 void SetThreadCount(int Count) { m_ThreadCount = max(1, min(Count, 512)); } 194 195 // Gets the number of threads currently set to be used for renders. 196 // Defaults to 2. 197 int GetThreadCount() const { return m_ThreadCount; } 198 199 // Clears any commands set via the AddCommand() method. 200 void ClearCommands() { m_Commands.clear(); } 201 202 // Adds the supplied std::string to the list of commands to be handled 203 // prior to the start of any render. The commands are processed in the 204 // order in which they appear in this list. A 'command' in this context 205 // is basically anything that could normally appear on the command-line 206 // of a POV-Ray console compile. 207 void AddCommand(const string& Command) { m_Commands.push_back(Command); } 208 209 // Returns a const reference to a vector<std::string> containing the 210 // current list of commands as added by AddCommand(), in order first 211 // to last. 212 const StringVector& GetCommands() const { return m_Commands; } 213 214 // Returns a copy of the vector<std::string> which holds the current 215 // list of commands as added by AddCommand(), in order first to last. 216 StringVector GetCommands() { return m_Commands; } 217 218 // Returns a non-const reference to the current POVMS_Object options 219 // instance. 220 POVMS_Object& GetOptions() { return m_Options; } 221 222 protected: 223 int m_ThreadCount; 224 UCS2StringVector m_IniFiles; 225 UCS2StringVector m_LibraryPaths; 226 StringVector m_Commands; 227 UCS2String m_SourceFile; 228 POVMS_Object m_Options; 229 } ; 230 231 // The integer values which may be returned from any of the VFE methods 232 // which return error codes. 233 enum 234 { 235 vfeNoError = 0, 236 vfeNoInputFile = 1024, // "No input file provided" 237 vfeRenderBlockSizeTooSmall, // "Specified block size is too small" 238 vfeFailedToWriteINI, // "Failed to write output INI file" 239 vfeFailedToSetSource, // "Failed to set source file" 240 vfeFailedToParseINI, // "Failed to parse INI file" 241 vfeIORestrictionDeny, // "I/O Restrictions prohibit access to file" 242 vfeFailedToParseCommand, // "Failed to parse command-line option" 243 vfeFailedToSetMaxThreads, // "Failed to set number of render threads" 244 vfeFailedToSendRenderStart, // "Failed to send render start request" 245 vfeRenderOptionsNotSet, // "Render options not set, cannot start render" 246 vfeAlreadyStopping, // "Renderer is already stopping" 247 vfeNotRunning, // "Renderer is not running" 248 vfeInvalidParameter, // "Something broke but we're not sure what" 249 vfeSessionExists, // "Only one session at once permitted in this version" 250 vfePOVMSInitFailed, // "Failed to initialize local messaging subsystem" 251 vfeOpenContextFailed, // "Failed to open context with core messaging subsystem" 252 vfeConnectFailed, // "Failed to connect to core messaging subsystem" 253 vfeInitializeTimedOut, // "Timed out waiting for worker thread startup" 254 vfeRequestTimedOut, // "Timed out waiting for request to be serviced" 255 vfeFailedToInitObject, // "Failed to initialize internal options storage" 256 vfeCaughtException, // "Caught exception of unexpected type" 257 vfeCaughtCriticalError, // "Caught critical error" 258 vfeDisplayGammaTooSmall, // "Specified display gamma is too small" 259 vfeFileGammaTooSmall, // "Specified file gamma is too small" 260 vfeUnsupportedOptionCombination, // "Unsupported option combination" 261 } ; 262 263 // The status flags (and mask combinations of flags) which may be returned 264 // from vfeSession::GetStatus(), or passed to vfeSession::SetEventMask(). 265 enum 266 { 267 stNone = 0x00000000, // No status to report 268 stClear = 0x00000001, // vfeSession::Clear() has been called 269 stReset = 0x00000002, // vfeSession::Reset() has been called 270 stFailed = 0x00000004, // Render failed 271 stSucceeded = 0x00000008, // Render succeeded 272 stStatusMessagesCleared = 0x00000010, // vfeSession::ClearStatusMessages() called 273 stOutputFilenameKnown = 0x00000020, // vfeSession::AdviseOutputFilename() called 274 stRenderingAnimation = 0x00000040, // vfeSession::SetRenderingAnimation() called 275 stAnimationFrameCompleted = 0x00000080, // vfeSession::AdviseFrameCompleted() called 276 stStreamMessage = 0x00000100, // One or more stream messages are available 277 stErrorMessage = 0x00000200, // One or more error messages are available 278 stWarningMessage = 0x00000400, // One or more warning messages are available 279 stStatusMessage = 0x00000800, // One or more status messages are available 280 stAnyMessage = 0x00000f00, // A mask of stStream, Error, Warning, and Status message flags. 281 stAnimationStatus = 0x00001000, // An animation status update is available 282 stBackendStateChanged = 0x00002000, // The state of the backend (reflected in pov_frontend::State) has changed 283 stRenderStartup = 0x00004000, // The render engine has started up 284 stRenderShutdown = 0x00008000, // The render engine has shut down 285 stShutdown = 0x10000000, // The session is shutting down 286 stCriticalError = 0x20000000, // A critical error (exception, POVMS memory alloc failure, etc) has occurred 287 stNoIgnore = 0x30000000, // A mask containing the status flags which can't be masked off 288 stNoClear = 0x30000000, // A mask containing the status flags which aren't cleared after a call to vfeSession::GetStatus() 289 } ; 290 291 // Used internally to track pause/resume status. 292 typedef enum 293 { 294 rqNoRequest = 0, 295 rqPauseRequest = 1, 296 rqResumeRequest = 2 297 } rqRequest; 298 299 // The data type returned by vfeSession::GetStatus(). 300 typedef int vfeStatusFlags ; 301 302 //////////////////////////////////////////////////////////////////////////// 303 // class vfeSession (vfe is short for Virtual FrontEnd). 304 // 305 // This class is the core of VFE. Each instance of a vfeSession represents 306 // a connection to the messaging subsystem of the POV-Ray backend, either 307 // locally or (in the future) remotely. It has a worker thread to handle 308 // communication with the backend asynchronously from the client (the 309 // software which created the session instance), and provides status 310 // feedback via either polling of the GetStatus() method, or via timed 311 // waits (again via GetStatus(), but this time using a timeout and an 312 // event notification system). 313 // 314 // Additionally vfeSession provides numerous convenience methods for 315 // setting up renders, monitoring renders (including retrieving status 316 // messages and render state), and associated maintenance such as the 317 // setting and retrieval of IO restrictions, display management, and 318 // critical event notifications. 319 // 320 // Some methods of vfeSession are pure virtual; it is required that each 321 // platform derive its own version in order to provide platform-specific 322 // functionality. Currently there are only six methods that must be provided 323 // in this way, summarized below: 324 // 325 // GetTemporaryPath() // return the path to a temporary storage area 326 // CreateTemporaryFile() // create a temporary filename (but don't open it) 327 // DeleteTemporaryFile() // delete a temporary file previously created 328 // GetTimestamp() // return a 64-bit one-millisecond resolution timestamp 329 // NotifyCriticalError() // asynchronously notify user of a critical error 330 // RequestNewOutputPath() // ask user for new output path if attempt to write file fails 331 // 332 // As can be seen, most of the above are trivial and in fact three of them 333 // already exist in pre-v3.7 platform-specific code. Refer to the windows 334 // reference implementation in vfe/win/ for well-commented examples of the 335 // implementation of the above mandatory methods, as well as a number of 336 // other optional ones. 337 class vfeSession 338 { 339 friend class vfeConsole; 340 friend class vfeParserMessageHandler; 341 friend class vfeRenderMessageHandler; 342 friend class vfeProcessRenderOptions; 343 friend class vfeDisplay; 344 friend class VirtualFrontEnd; 345 346 public: 347 // Our DisplayCreator functor - see vfeSession::SetDisplayCreator(). 348 typedef boost::function<vfeDisplay *(unsigned int, unsigned int, GammaCurvePtr, vfeSession *session, bool)> DisplayCreator; 349 typedef enum 350 { 351 mUnclassified = 0, 352 mDebug, 353 mInformation, 354 mWarning, 355 mPossibleError, 356 mError, 357 mAnimationStatus, 358 mGenericStatus, 359 mDivider 360 } MessageType ; 361 362 //////////////////////////////////////////////////////////////////////// 363 // class MessageBase. 364 // 365 // MessageBase encapsulates the various types of messages that may be 366 // returned from the base POV-Ray code. Each message has associated with 367 // it the ID of the session which generated it, a timestamp, and a type. 368 // The message itself is stored as a std::string. This base class is 369 // specialized into several more specific message types. 370 class MessageBase 371 { 372 public: 373 MessageBase(const vfeSession& session) : 374 m_Id(session.GetID()), m_TimeStamp (session.GetTimestamp()), m_Type(mUnclassified) {} 375 MessageBase(const vfeSession& session, MessageType type, string msg = "") : 376 m_Id(session.GetID()), m_TimeStamp (session.GetTimestamp()), m_Type(type), m_Message(msg) {} 377 virtual ~MessageBase() {} 378 379 POV_LONG m_TimeStamp; 380 MessageType m_Type; 381 string m_Message; 382 int m_Id; 383 } ; 384 385 //////////////////////////////////////////////////////////////////////// 386 // class GenericMessage. 387 // 388 // GenericMessage builds on MessageBase by further providing the line, 389 // column, and filename of the SDL which caused the message generation. 390 class GenericMessage : public MessageBase 391 { 392 public: 393 GenericMessage(const vfeSession& session) : 394 MessageBase(session), m_Line(0), m_Col(0) {} 395 GenericMessage(const vfeSession& session, MessageType type, string msg, const UCS2String file = UCS2String(), int line = 0, int col = 0) : 396 MessageBase (session, type, msg), m_Filename(file), m_Line(line), m_Col(col) {} 397 virtual ~GenericMessage() {} 398 399 int m_Line; 400 int m_Col; 401 UCS2String m_Filename; 402 } ; 403 404 //////////////////////////////////////////////////////////////////////// 405 // class StatusMessage. 406 // 407 // StatusMessage builds on MessageBase to encapsulate the messages that 408 // are generated by the core code during processing of a scene. This 409 // includes anything from parse status all the way through to final 410 // render stats. It has an optional delay member which is set by the 411 // vfe code to suggest to the client that after displaying the current 412 // message (the one the delay is retrieved with), it may like to delay 413 // that many milliseconds before erasing it and displaying the next. 414 // (This is of course only relevent for temporary display locations, 415 // such as in the status bar of a UI-based client implementation). 416 class StatusMessage : public MessageBase 417 { 418 public: 419 StatusMessage(const vfeSession& session) : 420 MessageBase(session), m_Delay(0), m_Frame(0), m_TotalFrames(0) {} 421 StatusMessage(const vfeSession& session, string msg, int m_Delay) : 422 MessageBase(session, mGenericStatus, msg), m_Delay(m_Delay), m_Frame(0), m_TotalFrames(0) {} 423 StatusMessage(const vfeSession& session, const UCS2String& file, int frame, int totalframes) : 424 MessageBase(session, mAnimationStatus), m_Delay(0), m_Filename(file), m_Frame(frame), m_TotalFrames(totalframes) {} 425 virtual ~StatusMessage() {} 426 427 int m_Delay; 428 int m_Frame; 429 int m_TotalFrames; 430 UCS2String m_Filename; 431 } ; 432 433 // The following queues are used to hold messages collected from the 434 // core code via vfeSession's worker thread. 435 typedef std::queue<GenericMessage> GenericQueue; 436 typedef std::queue<StatusMessage> StatusQueue; 437 typedef std::queue<MessageBase> ConsoleQueue; 438 439 // Construct a new instance of a vfeSession. An optional ID may be 440 // provided (which defaults to 0 if not). This ID is opaque to the 441 // VFE code itself - it only has meaning to the client software. It 442 // can be used to differentiate between sessions in a multiple- 443 // session implementation. If you are not implementing such a client 444 // it is sufficient to leave it at the default value. 445 vfeSession(int id = 0); 446 virtual ~vfeSession(); 447 448 // Convenience method to ensure the frontend connection (an internal 449 // concept representing the connection between VFE and the POV-Ray 450 // internal code) was created successfully. It will throw an exception 451 // of type pov_base::Exception if the connection does not exist. 452 void CheckFrontend() const { if (m_Frontend == NULL) throw POV_EXCEPTION_STRING("Frontend not connected"); } 453 454 // Clears many of the internal state information held by VFE regarding 455 // a render. Typically called before starting a new render. Included in 456 // the clear are the failure/success status, cancel request state, 457 // error code, percent complete, number of pixels rendered, total pixels 458 // in render, current animation frame, and total animation frame count. 459 // If the optional Notify flag is set (defaults to true), a status event 460 // of type stClear is generated. Note that this method does not empty the 461 // message queues (see Reset() for that). 462 virtual void Clear(bool Notify = true); 463 464 // Resets a session - this not only does the same work as vfeSession::Clear 465 // (without a stClear notification) but it also empties all the message 466 // queues, clears the input and output filenames, clears any animation 467 // status information, resets the status flags and clears the event mask. 468 // It will then generate a stReset notification. 469 virtual void Reset(); 470 471 // Clears all messages from the status message queue. 472 virtual void ClearStatusMessages(); 473 474 // Returns true if a fatal error message has been received since the 475 // last call to vfeSession::Clear(). Note that in the context of VFE 476 // only errors that will halt a render request are considered 'fatal'. 477 virtual bool HadErrorMessage() const { return m_HadErrorMessage; } 478 479 // Return true if the render is considered to have succeeded. In the 480 // case of an animation, this relates to all requested frames being 481 // processed, not each individual frame. The client is generally 482 // notified of render completion via the status event notification 483 // system, and then calls this method to find out the result. 484 virtual bool Succeeded() const { return m_BackendThreadExited == false && m_Succeeded; } 485 486 // The converse of vfeSession::Succeeded(), with the caveat that it 487 // will be set upon the failure of any frame in an animation, not that 488 // of all frames. 489 virtual bool Failed() const { return m_Failed; } 490 491 // Used to set up a session with a POV backend. Accepts two 492 // parameters - a destination (vfeDestInfo) and authorization 493 // (vfeAuthInfo), both pointers. Currently these must be NULL. 494 // 495 // Intialize() will call the Reset() method, and then create 496 // the session's worker thread, at which time it will wait on 497 // an event for the worker thread to signal that it has completed 498 // its own initialization. By default the worker thread setup is 499 // considered to have failed if it has not signalled within three 500 // seconds (elapsed time). However to aid debugging this is extended 501 // to 123 seconds if _DEBUG is defined. 502 // 503 // If the startup is successful, this method returns vfeNoError after 504 // issuing a stBackendStateChanged status notification. Otherwise it 505 // will either set m_LastError to vfeInitializeTimeout and return that 506 // same value, or it will retrieve the error code set by the worker 507 // thread, wait for the worker thread to exit, and return that code. 508 // 509 // The worker thread itself is responsible for creating the actual 510 // connection with the backend code. 511 virtual int Initialize(vfeDestInfo *Dest, vfeAuthInfo *Auth); 512 513 // Returns the ID passed to the class constructor. Defaults to 0 if not specified. 514 virtual int GetID() const { return m_Id ; } 515 516 // Returns a copy of the shared pointer containing the current instance 517 // of a pov_frontend::Display-derived render preview instance, which may 518 // be NULL. 519 virtual boost::shared_ptr<Display> GetDisplay() const; 520 521 // If a VFE implementation has provided a display creator functor via 522 // vfeSession::SetDisplayCreator(), this method will call it with the 523 // width, height, gamma factor, and default visibility flag of the requested 524 // render preview window. Otherwise it will return whatever the default display 525 // creator returns (see SetDisplayCreator()). 526 // 527 // It is called when the core POV-Ray code requests that a render preview 528 // window be created. The display instance returned is expected to conform 529 // to the definition of the pov_frontend::Display class (but it typically 530 // a platform-specific derivative of that.) 531 virtual vfeDisplay *CreateDisplay(unsigned int width, unsigned int height, GammaCurvePtr gamma, bool visible = false); 532 533 // Used by VFE implementations to allow their own custom pov_frontend::Display 534 // derived render preview window class to be created when the main POV-Ray code 535 // wants a preview window. The passed parameter is a DisplayCreator (see the 536 // typedef earlier on in vfeSession and the example in CreateFrontend() and 537 // WinDisplayCreator() of source/windows/pvfrontend.cpp). 538 // 539 // If this method is not called, the display creator defaults to 540 // vfeSession::DefaultDisplayCreator(). 541 virtual void SetDisplayCreator(DisplayCreator creator) { m_DisplayCreator = creator; } 542 543 // Returns a pointer to the internal VirtualFrontendInstance used by the session. 544 // Generally a client should not need this - if there is some good reason to get 545 // at the frontend, it probably means that there is functionality missing from 546 // vfeFrontend (which, after all, is intended to wrap the actual frontend). 547 virtual VirtualFrontEnd *GetFrontend() const { return m_Frontend ; } 548 549 // This method returns the current set of status flags as set by the worker 550 // thread and various other parts of vfeSession. The status flags returned 551 // are not affected by any event mask set (see vfeSession::SetEventMask() 552 // for more information), but whether or not a wait occurs. 553 // 554 // Two parameters are accepted (both optional). The first one, a bool, 555 // determines whether or not the internal copy of the status flags is 556 // cleared prior to returning. By default, this is the case. Note that 557 // flags identified by the stNoClear mask cannot be cleared by this method 558 // and will remain set until vfeSession::Reset() is called. See the definition 559 // of the status flags enum in vfesession.h for more information on flags. 560 // Note that even if the flags are cleared, an stClear notification does not 561 // get set. 562 // 563 // The second parameter - an int - sets the wait time. If not specified, it 564 // defaults to -1, which means wait indefinitely for an event. If set to 0, 565 // it effectively turns this method into a status polling function, since 566 // there will never be a wait. Otherwise the parameter specifies the maximum 567 // number of milliseconds to wait on the status notification event before 568 // returning the status flags (note that there is no indication of timeout). 569 // 570 // Typical usage of this method by a client that has its own status handling 571 // thread would be for the thread to call this method with an indefinite 572 // timeout, and depend on the stShutdown event and status notification to 573 // determine if its host application wants it to exit. stShutdown events can 574 // be generated by the host calling vfeSession::Shutdown() (it is safe for 575 // this to be called from any thread multiple times). 576 // 577 // A client that does not want to devote a thread to status processing 578 // would typically call this method in polling mode, with perhaps a short 579 // timeout, depending on the implementation. (The sample console example 580 // provided for VFE does this). 581 virtual vfeStatusFlags GetStatus(bool Clear = true, int WaitTime = -1) ; 582 583 // This method allows a client to specify a set of status flags that it 584 // wants to allow to generate events. An 'event' in terms of VFE is the 585 // case where an action (typically that of the worker thread) occurs that 586 // would set, in the internal status flags, a status indication that is 587 // not otherwise masked out by a call to this method. The net result of 588 // an event being generated is that a thread waiting via a call to the 589 // vfeSession::GetStatus() method with a non-zero timeout will get woken 590 // up immediately. Note that this will occur even if the flag is already 591 // set in the internal flags (e.g. GetStatus() was called with clear set 592 // to false). Note also that if more than one client thread has called 593 // GetStatus() and is sleeping on an event, only one will be woken. 594 // 595 // By default, all events are allowed (this is as if SetEventMask() had 596 // been called with a parameter of ~stNone). 597 // 598 // Be aware that some events may not be masked out (e.g. stShutdown, 599 // stCriticalError). See the definition of the status flags for more 600 // detail. 601 virtual void SetEventMask(vfeStatusFlags Mask = stNone) { m_EventMask = vfeStatusFlags (Mask | stNoIgnore); } 602 603 // Returns the current event mask (see vfeSession::SetEventMask()). 604 virtual vfeStatusFlags GetEventMask() const { return vfeStatusFlags(m_EventMask); } 605 606 // Returns true if the POV-Ray code is in a state where a pause request 607 // both makes sense and can be accepted. Typical use of this method is 608 // to call it each time a stBackendStateChanged event occurs, and to use 609 // the returned value to configure a client user interface (e.g. to gray 610 // out or enable a pause button or menu item). 611 // 612 // Throws a pov_base::Exception if the frontend does not exist (i.e. 613 // vfeSession::Initialize() hasn't been called or failed when called). 614 virtual bool IsPausable() const; 615 616 // Used similarly to vfeFrontend::IsPausable(), but returns the actual 617 // pause/not paused state. 618 // 619 // Throws a pov_base::Exception if the frontend does not exist (i.e. 620 // vfeSession::Initialize() hasn't been called or failed when called). 621 virtual bool Paused() const; 622 623 // Requests the POV-Ray backend code to pause whatever it is doing by entering 624 // an idle loop with calls to pov_base::Delay(). This method is synchronous 625 // and thus a delay of up to three seconds can occur waiting for the backend 626 // to respond. If a timeout occurs, m_LastError is set to vfeRequestTimedOut 627 // and this method returns false. Otherwise, m_LastError is set to vfeNoError 628 // and the return value is set according to whether the backend accepted the 629 // request (true) or rejected it (false). Typically it will only reject a 630 // pause request if it is not in a pausable state (e.g. it's not rendering). 631 // 632 // Implementation note: the pause request itself is actually proxied via the 633 // session's worker thread, since the POV-Ray messaging system requires that 634 // all such requests come from the thread that created the session (this is 635 // to allow internal dispatching of message replies to the right place). The 636 // net effect of this is that the worker thread won't be doing anything else 637 // (such as dispatching messages) once it starts processing this request. 638 // 639 // Throws a pov_base::Exception if the frontend does not exist (i.e. 640 // vfeSession::Initialize() hasn't been called or failed when called). 641 virtual bool Pause(); 642 643 // If called with on == true, tells POV-Ray to pause rendering after the end 644 // of each frame of an animation (but has no effect on non-animation renders). 645 // This is almost the same as calling Pause() at the right time, but without 646 // the timing constraints associated with that (for fast renders, the next 647 // frame could have started before the frontend's pause request was processed). 648 // The pause is not applied after the last frame. 649 // 650 // Note that the neither the rendering engine nor the parser are actually 651 // paused (in the usual sense of the word) by this feature; the implementation 652 // simply does not start the next frame after one ends. 653 // 654 // A render can be resumed by calling Resume() as per normal. 655 // 656 // Internally, this option defaults to false, and is reset whenever Clear() 657 // or Reset() is called. 658 virtual void PauseWhenDone(bool on) { m_PauseWhenDone = on; } 659 660 // get the current pause when done setting. 661 virtual bool GetPauseWhenDone(void) { return m_PauseWhenDone; } 662 663 // The converse of vfeSession::Pause(). All the same considerations apply. 664 virtual bool Resume(); 665 666 // Returns true if an animation is being rendered. The result can only 667 // be considered valid if the render has actually been started. 668 virtual bool RenderingAnimation() const { return m_RenderingAnimation; } 669 670 // Returns the current frame of an animation. Only valid once the internal 671 // state has reached kStarting (see the stBackendStateChanged status flag). 672 // The typical way of reading this is to wait for a stAnimationStatus event 673 // and then call GetCurrentFrame(). 674 virtual int GetCurrentFrame() const { return m_CurrentFrame; } 675 676 // Returns the total frame count of an animation. Valid once the internal 677 // state has reached kStatring. The typical way of reading this is to wait 678 // for a stAnimationStatus flag and then call GetTotalFrames(). 679 virtual int GetTotalFrames() const { return m_TotalFrames; } 680 681 // Returns the percentage of the render that has completed, in terms of 682 // pixel count, as an int in the range 0 to 100. The internal code that 683 // updates this value does so in response to a progress message from 684 // the backend, and since this also generates a status message, your 685 // status message handling code is a good place to call this method from. 686 virtual int GetPercentComplete() const { return m_PercentComplete; } 687 688 // Returns count of pixels rendered. Same consideration for update 689 // applies as does for vfeSession::GetPercentComplete(). 690 virtual int GetPixelsRendered() const { return m_PixelsRendered; } 691 692 // Returns total pixel count. This value is only valid once at least 693 // one render progress message has been received from the backend. 694 virtual int GetTotalPixels() const { return m_TotalPixels; } 695 696 //////////////////////////////////////////////////////////////////////// 697 // Return an absolute path including trailing path separator. 698 // *nix platforms might want to just return "/tmp/" here. 699 // NB this method is pure virtual. 700 virtual UCS2String GetTemporaryPath(void) const = 0; 701 702 //////////////////////////////////////////////////////////////////////// 703 // Return a valid and unique temporary filename. 704 // NB this method is pure virtual. 705 virtual UCS2String CreateTemporaryFile(void) const = 0; 706 707 //////////////////////////////////////////////////////////////////////// 708 // Delete the filename passed. Platforms may like to check that the file 709 // specified lies either in a valid temporary path location or is a valid 710 // temporary filename (see e.g. vfeSession::GetTemporaryPath()). 711 // NB this method is pure virtual. 712 virtual void DeleteTemporaryFile(const UCS2String& filename) const = 0; 713 714 //////////////////////////////////////////////////////////////////////// 715 // Return a timestamp to be used internally for queue sorting etc. The 716 // value returned must be 64-bit and in milliseconds; the origin of the 717 // count is not important (e.g. milliseconds since 1/1/1970, or whatever 718 // it doesn't matter), as long as it is consistent value (milliseconds 719 // since system boot is NOT a valid value since it will change each boot). 720 // Also please don't call time() and multiply by 1000 since vfe wants at 721 // least 100ms precision (so it can do sub-one-second event timing). 722 // 723 // It's also important that the count not go backwards during the life 724 // of a vfeSession instance; this means you should attempt to detect wall 725 // clock changes by caching the last value your implementation returns 726 // and adding an appropriate offset if you calculate a lower value later 727 // in the session. 728 // 729 // NB this method is pure virtual. 730 virtual POV_LONG GetTimestamp(void) const = 0; 731 732 ///////////////////////////////////////////////////////////////////////// 733 // This method will get called on POVMS critical errors (e.g. cannot 734 // allocate memory, amongst other things). Note that you should not 735 // assume that you can e.g. allocate memory when processing this call. 736 // 737 // Before calling this function vfe sets a flag that prevents the worker 738 // thread from processing any more messages; it will wait for you to 739 // call Shutdown(). Your UI thread can find out if this method has been 740 // called by checking for the presence of the stCriticalError status bit 741 // returned from vfeSession::GetStatus() (note that this bit is not 742 // necessarily already set at the time the method is called though). 743 // 744 // If you are running a genuine virtual frontend (e.g. stateless HTTP 745 // interface), we may want to set a flag to display the message later 746 // rather than pop up a messagebox on the local windowstation. Otherwise 747 // you would probably display the message immediately. 748 virtual void NotifyCriticalError(const char *message, const char *file, int line) = 0; 749 750 // This method causes a shutdown of the vfeSession instance. Specifically 751 // it will set a flag asking the worker thread to exit, issue a 752 // stShutdown notification, and then wait for the worker thread to exit. 753 // The optional boolean parameter (default false) is used by the caller 754 // to indicate a forced shutdown of the worker thread is permissible 755 // (e.g. a kill if it doesn't shutdown gracefully within a reasonable 756 // period of time). It is not mandatory to implement the forced feature. 757 virtual void Shutdown(bool forced = false); 758 759 // Requests the backend to cancel the current render. Returns vfeNotRunning 760 // if there is no current render, vfeAlreadyStopping if a stop has already 761 // been requested, or vfeNoError otherwise. Also sets m_LastError in all 762 // cases. Note that this request is handled by the worker thread, like for 763 // vfeSession::Pause(), but unlike that request this one is handled 764 // asynchronously. This means you need to be prepared to handle the situation 765 // that even though you've called CancelRender(), the session hasn't caught 766 // up with the processing of the request yet. 767 virtual int CancelRender(void); 768 769 // Start a render. Will set m_LastError and return vfeRenderOptionsNotSet 770 // if you didn't call vfeSession::SetOptions() first. Otherwise will attempt 771 // to start the render; if this fails vfeFailedToSendRenderStart is returned. 772 // If the start attempt succeeds (note this is distinct from the start itself 773 // actually succeeding - all that the lack of a vfeFailedToSendRenderStart 774 // error means is that the start request was successfully sent to the backend) 775 // then a stRenderStartup notification is sent and the state is changed to 776 // kStarting. 777 // 778 // If the start attempt fails (signified by the receipt of a std::exception), 779 // the exception code will, in the case of a pov_base::Exception, be extracted 780 // and stored in m_LastError and returned; otherwise (not pov_base::Exception), 781 // m_LastError is set to -1. In either case, a failed status is set (so that 782 // vfeSession::Failed() will return true), and, if a fatal error message has 783 // not already been queued, the text of the exception will be added to both 784 // the status and error message queues. 785 virtual int StartRender(void); 786 787 // Sets the options to be used on the next render. Accepts a vfeRenderOptions 788 // instance as its only parameter, and returns any one of a number of possible 789 // error codes (and sets m_LastError), as documented below: 790 // 791 // vfeFailedToInitObject - this is an internal error 792 // vfeFailedToSetMaxThreads - self-explanatory 793 // vfeFailedToParseINI - an INI file specified could not be parsed 794 // vfeFailedToSetSource - the source file specified could not be set 795 // vfeFailedToParseCommand - a command-line option was invalid 796 // vfeNoInputFile - no input file specified either directly or via INI 797 // vfeRenderBlockSizeTooSmall - self-explanatory 798 // vfeFailedToWriteINI - a request to write the render options to an INI file failed 799 // vfeUnsupportedOptionCombination - at least two of the supplied options don't combine 800 // 801 // If vfeRenderOptions explicitly specifies a source file, it will override 802 // any set via a parsed INI file. Furthermore, any source file set via a 803 // command-line option overrides both of the above. 804 // 805 // Note that it is your responsibility to add any default INI files that should 806 // be processed to the INI file list; neither SetOptions() nor any other part 807 // of the VFE or POV-Ray code will do that for you. This includes non-platform 808 // specific files such as a potential povray.ini in the CWD. 809 virtual int SetOptions (vfeRenderOptions& opts); 810 811 // Clears any options set by vfeSession::SetOptions(). 812 virtual void ClearOptions(void) { m_RenderOptions.Clear(); m_OptionsSet = false; } 813 814 // Returns true if the named option (e.g. "Output_To_File") is present in the 815 // render options. Will throw an exception if the options have not been set, or 816 // if the option name is invalid. 817 virtual bool OptionPresent(const char *OptionName); 818 819 // Will return the value of the named option, or the default value if it is not 820 // set. Will throw an exception for the same reasons as the OptionPresent() method. 821 // NOTE: this method won't always return what you expect; for example, if the user 822 // does not explicitly set the output file name, it won't be in the options, and 823 // thus won't be returned. That is to say, don't expect these methods to return 824 // the default values applied by the renderer in the absense of a specific value. 825 // This also applies to partial values, e.g. if the user sets "Output_File_Name=foo", 826 // we would return "foo", rather than for example "foo.png". 827 bool GetBoolOption(const char *OptionName, bool DefaultVal); 828 int GetIntOption(const char *OptionName, int DefaultVal); 829 float GetFloatOption(const char *OptionName, float DefaultVal); 830 std::string GetStringOption(const char *OptionName, const char *DefaultVal); 831 UCS2String GetUCS2StringOption(const char *OptionName, const UCS2String& DefaultVal); 832 833 // Helper method intended to tell VFE if it is running in a console-based 834 // client. If called with its boolean parameter set to true, the console 835 // word-wrap width will be set to 80, and an internal flag is set. Both 836 // this flag and the default wrap width are initially set to assume that 837 // a console build is in use, so a client platform only needs to call this 838 // if they are UI-based. If the value passed is false, the wrap width is 839 // set to 999, and furthermore any future warning or error messages received 840 // by the worker thread will additionally be added to the status message 841 // queue, along with the filename, line, and column where they occurred 842 // (assuming this was provided). UI-based clients can then, when they 843 // retrieve the status message, use its content to auto-display the error 844 // location in the source file if they so choose. 845 virtual void OptimizeForConsoleOutput(bool On) { m_OptimizeForConsoleOutput = On; m_ConsoleWidth = On ? 80 : 999; } 846 847 // Returns the raw POV-Ray internal state (e.g. kRendering etc) 848 virtual State GetBackendState() const { return m_BackendState; } 849 850 // Translates a state as returned from vfeSession::GetBackendState() into a string. 851 virtual const char *GetBackendStateName(void) const ; 852 853 // Return the input filename. This is not valid until vfeSession::SetOptions() 854 // has been called successfully. 855 virtual UCS2String GetInputFilename(void) const { return m_InputFilename; } 856 857 // Return the output filename. You should not call this until you have received 858 // a stOutputFilenameKnown status event. While it may be tempting to assume 859 // that the output filename is known as soon as the options are set, this is 860 // not necessarily the case - consider animations for example. Note it is 861 // also possible that you will never receive an stOutputFilenameKnown event 862 // since it is of course possible that output to file is turned off. 863 virtual UCS2String GetOutputFilename(void) const { return m_OutputFilename; } 864 865 // This method returns true if the current options specify that an output 866 // image should be written. It is only valid if vfeSession::SetOptions() 867 // has been called successfully. 868 virtual bool OutputToFileSet(void) const { return m_OutputToFileSet; } 869 870 // This method returns true if the current platform supports writing image 871 // output to STDOUT. Platforms that do not support this should override it. 872 virtual bool ImageOutputToStdoutSupported(void) const { return true; } 873 874 // This method returns the currently-set render width, in pixels. 875 // It is only valid if vfeSession::SetOptions() has been called successfully. 876 virtual int GetRenderWidth(void) const { return m_RenderWidth; } 877 878 // This method returns the currently-set render height, in pixels. 879 // It is only valid if vfeSession::SetOptions() has been called successfully. 880 virtual int GetRenderHeight(void) const { return m_RenderHeight; } 881 882 // This method returns a reference to the vfeRenderOptions instance stored 883 // within vfe. After vfeSession::SetOptions() is called successfully, the 884 // supplied options are copied into the internal instance. 885 virtual vfeRenderOptions& GetOptions() { return m_RenderOptions; } 886 887 // Fetches one message from either the generic, status, or console message 888 // queues, whichever has the earliest timestamp. Returns true if a message 889 // is fetched, otherwise false (meaning all the queues are empty). It expects 890 // two parameters - a reference to a MessageType, in which the type of the 891 // returned message is stored, and a std::string, which will be set to the 892 // actual message text. Note that linefeeds are not appended. 893 // 894 // This method is primarily useful for console-style displays as it discards 895 // any additional meta-information the message may have had, such as the 896 // line number of an error. (Note that this does not mean the line number 897 // cannot be in the message string; it may very well be). 898 virtual bool GetNextCombinedMessage (MessageType &Type, string& Message); 899 900 // Gets the next non-status message (meaning generic or console messages) 901 // from the aforementioned queues; whichever is the earliest. Returns false 902 // if there is no message to fetch, otherwise will set the message type, 903 // filename, line, and column parameters supplied. If the message retrieved 904 // did not contain this information, the relevent entry is either set to 0 905 // (line and column) or the empty string (filename). The filename parameter 906 // is a UCS2String. 907 virtual bool GetNextNonStatusMessage (MessageType &Type, string& Message, UCS2String& File, int& Line, int& Col); 908 909 // Gets the next non-status message (meaning generic or console messages) 910 // from the aforementioned queues; whichever is the earliest. Returns false 911 // if there is no message to fetch, otherwise will set the message type, 912 // filename, line, and column parameters supplied. If the message retrieved 913 // did not contain this information, the relevent entry is either set to 0 914 // (line and column) or the empty string (filename). The filename parameter 915 // is a std::string. 916 virtual bool GetNextNonStatusMessage (MessageType &Type, string& Message, string& File, int& Line, int& Col); 917 918 // Gets the next non-status message (meaning generic or console messages) 919 // from the aforementioned queues; whichever is the earliest. Returns false 920 // if there is no message to fetch, otherwise will set the message type 921 // and text content parameters supplied. Any additional meta-information 922 // that may have been contained in the message is discarded. 923 virtual bool GetNextNonStatusMessage (MessageType &Type, string& Message); 924 925 // Returns false if there are no messages in the status message 926 // queue, otherwise removes the oldest status message from the 927 // queue and copies it into the StatusMessage reference supplied 928 // as a parameter, then returns true. 929 virtual bool GetNextStatusMessage (StatusMessage& Message); 930 931 // Returns false if there are no messages in the generic message 932 // queue, otherwise removes the oldest message from the queue and 933 // copies it into the GenericMessage reference supplied as a 934 // parameter, then returns true. 935 virtual bool GetNextGenericMessage (GenericMessage& Message); 936 937 // Returns false if there are no messages in the console message 938 // queue, otherwise removes the oldest message from the queue and 939 // copies it into the MessageBase reference supplied as a parameter, 940 // then returns true. 941 virtual bool GetNextConsoleMessage (MessageBase& Message); 942 943 // Returns a std::string potentially useful for displaying in the status 944 // line (or other similar UI element) of a UI-based client implementation. 945 // The VFE internal code takes care of setting this to what it considers 946 // reasonable values and issuing either a stStatusMessage or stAnimationStatus 947 // event notification, as appropriate. Upon receiving either of the above 948 // events therefore you may like to simply call this method and place the 949 // returned value wherever suitable, overwriting the previous value.2 950 virtual string GetStatusLineMessage() { return m_StatusLineMessage; } 951 952 // Sets the maximum number of status messages that will be stored in the 953 // status queue. If this limit is reached, the oldest message will be 954 // discarded each time a new message is added. The default value is -1, 955 // which means that there is no limit. 956 virtual void SetMaxStatusMessages (int Max) { m_MaxStatusMessages = Max; } 957 958 // Sets the maximum number of generic messages that will be stored in the 959 // status queue. If this limit is reached, the oldest message will be 960 // discarded each time a new message is added. The default value is -1, 961 // which means that there is no limit. 962 virtual void SetMaxGenericMessages (int Max) { m_MaxGenericMessages = Max; } 963 964 // Sets the maximum number of console messages that will be stored in the 965 // status queue. If this limit is reached, the oldest message will be 966 // discarded each time a new message is added. The default value is -1, 967 // which means that there is no limit. 968 virtual void SetMaxConsoleMessages (int Max) { m_MaxConsoleMessages = Max; } 969 970 // Returns a string giving a short english description of the error code 971 // supplied as the only parameter. If no parameter is supplied, the default 972 // value (-1) instructs the method to instead use the value of m_LastError. 973 virtual const char *GetErrorString(int code = -1) const ; 974 975 // Returns true if opening the given file in the specified mode is to 976 // be permitted. It is allowed to ask the user, so this method could 977 // take some time to return (especially if user is not at workstation). 978 // The default implementation simply returns true. Platforms should 979 // override this method and do something more useful (see the Windows 980 // implementation in vfe/win/vfeplatform.cpp). 981 virtual bool TestAccessAllowed(const Path& file, bool isWrite) const { return true; } 982 983 // Allows you to manually set the console wrap width. 984 // The supplied value is clipped to the range 80-999. 985 virtual void SetConsoleWidth(int width) { m_ConsoleWidth = max(min(999,width),80); } 986 987 // Return the current console wrap width. 988 virtual int GetConsoleWidth(void) { return m_ConsoleWidth; } 989 990 // Clear all IO Restriction-related paths previously set. 991 virtual void ClearPaths() { m_ReadPaths.clear(); m_WritePaths.clear(); m_ExcludedPaths.clear(); } 992 993 // Adds the supplied path to the list of allowed read paths, along with 994 // the recursive flag (meaning paths under that path are also allowed). 995 // The supplied path is a pov_base::Path instance. 996 virtual void AddReadPath(const Path& path, bool recursive = true) { m_ReadPaths.push_back(IOPath(path, recursive)); } 997 998 // Adds the supplied path to the list of allowed read paths, along with 999 // the recursive flag (meaning paths under that path are also allowed). 1000 // The supplied path is a UCS2String. 1001 virtual void AddReadPath(const UCS2String& path, bool recursive = true) { m_ReadPaths.push_back(IOPath(path, recursive)); } 1002 1003 // Adds the supplied path to the list of allowed read paths, along with 1004 // the recursive flag (meaning paths under that path are also allowed). 1005 // The supplied path is a std::string. 1006 virtual void AddReadPath(const string& path, bool recursive = true) { m_ReadPaths.push_back(IOPath(path, recursive)); } 1007 1008 // Adds the supplied path to the list of allowed read paths. 1009 // The supplied path is a pre-constructed IOPath instance. 1010 virtual void AddReadPath(const IOPath& path) { m_ReadPaths.push_back(path); } 1011 1012 // Adds the supplied path to the list of allowed write paths, along with 1013 // the recursive flag (meaning paths under that path are also allowed). 1014 // The supplied path is a pov_base::Path instance. 1015 virtual void AddWritePath(const Path& path, bool recursive = true) { m_WritePaths.push_back(IOPath(path, recursive)); } 1016 1017 // Adds the supplied path to the list of allowed write paths, along with 1018 // the recursive flag (meaning paths under that path are also allowed). 1019 // The supplied path is a UCS2String. 1020 virtual void AddWritePath(const UCS2String& path, bool recursive = true) { m_WritePaths.push_back(IOPath(path, recursive)); } 1021 1022 // Adds the supplied path to the list of allowed write paths, along with 1023 // the recursive flag (meaning paths under that path are also allowed). 1024 // The supplied path is a std::string. 1025 virtual void AddWritePath(const string& path, bool recursive = true) { m_WritePaths.push_back(IOPath(path, recursive)); } 1026 1027 // Adds the supplied path to the list of allowed write paths. 1028 // The supplied path is a pre-constructed IOPath instance. 1029 virtual void AddWritePath(const IOPath& path) { m_WritePaths.push_back(path); } 1030 1031 // Adds the supplied path to the list of excluded paths, along with the 1032 // recursion flag. A path in the exclusion list is never allowed to be 1033 // written to, even if it would be otherwise permitted by a write path. 1034 // Unlike read and write paths, which may be specified by users, the 1035 // intent of excluded paths is to allow client implementations to hard- 1036 // code certain paths that may never be written to, such as the location 1037 // of the platform's master configuration files (that presumably contain 1038 // contain the user-specified read and write path settings). The supplied 1039 // path is a pov_base::Path instance. 1040 virtual void AddExcludedPath(const Path& path, bool recursive = true) { m_ExcludedPaths.push_back(IOPath(path, recursive)); } 1041 1042 // Adds the supplied path to the list of excluded paths, along with the 1043 // recursion flag. The supplied path is a UCS2String. 1044 virtual void AddExcludedPath(const UCS2String& path, bool recursive = true) { m_ExcludedPaths.push_back(IOPath(path, recursive)); } 1045 1046 // Adds the supplied path to the list of excluded paths, along with the 1047 // recursion flag. The supplied path is a std::string. 1048 virtual void AddExcludedPath(const string& path, bool recursive = true) { m_ExcludedPaths.push_back(IOPath(path, recursive)); } 1049 1050 // Adds the supplied path to the list of excluded paths, along with the 1051 // recursion flag. The supplied path is a pre-constructed IOPath instance. 1052 virtual void AddExcludedPath(const IOPath& path) { m_ExcludedPaths.push_back(path); } 1053 1054 // Returns a const reference to the list of permitted read paths. 1055 virtual const IOPathVector& GetReadPaths() const { return m_ReadPaths; } 1056 1057 // Returns a copy of the list of permitted read paths. 1058 virtual IOPathVector GetReadPaths() { return m_ReadPaths; } 1059 1060 // Returns a const reference to the list of permitted write paths. 1061 virtual const IOPathVector& GetWritePaths() const { return m_WritePaths; } 1062 1063 // Returns a copy of the list of permitted write paths. 1064 virtual IOPathVector GetWritePaths() { return m_WritePaths; } 1065 1066 // Returns a const reference to the list of excluded paths. 1067 virtual const IOPathVector& GetExcludedPaths() const { return m_ExcludedPaths; } 1068 1069 // This static method is used to return the vfeSession associated with 1070 // the calling thread (if any). In a full multi-session-enabled 1071 // implementation of vfe, it would look up the session from a list of 1072 // active sessions keyed with the value returned from GetThreadID(). 1073 // Currently as only one session is supported (this is enforced in the 1074 // vfeSession::Initialize() method) it simply returns the value of a 1075 // global variable. 1076 static vfeSession *GetSessionFromThreadID() ; 1077 1078 // These methods just return whether or not the named option is in effect. 1079 // They are only valid once vfeParserMessageHandler::Options has been called. 1080 virtual bool GetUsingAlpha() { return m_UsingAlpha; } 1081 virtual bool GetClocklessAnimation() { return m_ClocklessAnimation; } 1082 virtual bool GetRealTimeRaytracing() { return m_RealTimeRaytracing; } 1083 1084 // return elapsed time in the render as milliseconds. only valid once the 1085 // state changs to rendering. 1086 virtual POV_LONG GetElapsedTime() { return GetTimestamp() - m_StartTime; } 1087 1088 virtual void AppendErrorMessage (const string& Msg); 1089 virtual void AppendWarningMessage (const string& Msg); 1090 virtual void AppendStatusMessage (const string& Msg, int RecommendedPause = 0); 1091 virtual void AppendStatusMessage (const boost::format& fmt, int RecommendedPause = 0); 1092 virtual void AppendWarningAndStatusMessage (const string& Msg, int RecommendedPause = 0) { AppendWarningMessage(Msg); AppendStatusMessage(Msg, RecommendedPause); } 1093 virtual void AppendErrorAndStatusMessage (const string& Msg, int RecommendedPause = 0) { AppendErrorMessage(Msg); AppendStatusMessage(Msg, RecommendedPause); } 1094 1095 // returns true if a render cancel was requested at some point since the render started. 1096 virtual bool GetCancelRequested() { return m_RenderCancelRequested | m_RenderCancelled ; } 1097 1098 // returns true if the main POV-Ray backend has shut down 1099 virtual bool BackendFailed() { return m_BackendThreadExited; } 1100 1101 protected: 1102 // All of the following are internal to vfe. 1103 virtual void SetFailed(); 1104 virtual void SetSucceeded (bool ok); 1105 virtual void AdviseOutputFilename(const UCS2String& Filename); 1106 virtual void AdviseFrameCompleted(); 1107 virtual void SetRenderingAnimation(); 1108 virtual void SetPercentComplete(int Percent) { m_PercentComplete = Percent; } 1109 virtual void SetPixelsRendered(int Rendered, int Total) { m_PixelsRendered = Rendered; m_TotalPixels = Total; } 1110 1111 virtual void AppendStreamMessage (MessageType type, const char *message, bool chompLF = false); 1112 virtual void AppendStreamMessage (MessageType type, const boost::format& fmt, bool chompLF = false); 1113 virtual void AppendErrorMessage (const string& Msg, const UCS2String& File, int Line = 0, int Col = 0); 1114 virtual void AppendWarningMessage (const string& Msg, const UCS2String& File, int Line = 0, int Col = 0); 1115 virtual void AppendAnimationStatus (int Frame, int Total, const UCS2String& Filename); 1116 1117 virtual void SetUsingAlpha() { m_UsingAlpha = true ; } 1118 virtual void SetClocklessAnimation() { m_ClocklessAnimation = true ; } 1119 virtual void SetRealTimeRaytracing() { m_RealTimeRaytracing = true ; } 1120 virtual void NotifyEvent(vfeStatusFlags Status); 1121 1122 virtual void BackendThreadNotify(); 1123 virtual void WorkerThread(); 1124 virtual void WorkerThreadStartup() {} 1125 virtual void WorkerThreadShutdown() {} 1126 1127 virtual bool ProcessFrontend (void); 1128 virtual bool ProcessCancelRender(void); 1129 virtual bool StopRender(const string& reason); 1130 1131 // This method allows your platform code to perform platform-specific actions 1132 // when a render stops (whether it succeeds or fails). A good example would 1133 // be to shrink the heap. Be aware that it is called in the context of the 1134 // worker thread, and that therefore on windowing systems where thread context 1135 // is relevent to making certain UI calls, it may not be possible to perform 1136 // certain UI actions here. For most platforms the default implementation 1137 // should be sufficient. 1138 virtual void RenderStopped(void); 1139 1140 // Platforms that support the ability to return excess heap memory to 1141 // the operating system should implement this method. 1142 virtual void ShrinkHeap() {} 1143 1144 // Hook this if you want to directly catch state change events (but if 1145 // you do, ensure you call back to the default implementation as well). 1146 virtual void StateChanged(pov_frontend::State NewState); 1147 1148 ///////////////////////////////////////////////////////////////////////// 1149 // This method will get called when a render completes and the image writing 1150 // code is unable to write the requested output file for some reason (e.g. 1151 // disk full, existing output file is read-only, or whatever). The return 1152 // value can determine any one of several possible actions the code will take. 1153 // It's up to you what you do here, but a typical example would be to display 1154 // an error dialog showing the reason (which will be a short string) and the old 1155 // path, and allow the user to browse for a new path (you may want to auto- 1156 // suggest one). It is allowable to perform tests yourself on the path to 1157 // obtain some OS-specific information as to why it failed in order to better 1158 // determine what to suggest as the new path (e.g. the the output path is 1159 // not writable due to insufficient privileges, you may want to default the 1160 // new path to the user's home directory). 1161 // 1162 // Any new path that is to be returned should be placed in NewPath. The parameter 1163 // CallCount will initially be 0, and represents the number of times the 1164 // method has been called for a given rendering; this allows you for example 1165 // to auto-default on the first call and prompt the user on subsequent ones. 1166 // (Note that if you do this and the auto-default succeeds, it's up to you to 1167 // notify the user that the output file is not what they originally asked for). 1168 // 1169 // You may want to place a timeout on this dialog if the session is running 1170 // an animation and return in the case of a timeout a default value. 1171 // 1172 // The return values can be any of the following: 1173 // 1174 // 0 : don't try again, leave the render without an output file but preserve 1175 // the state file (so a render with +c will reload the image data). 1176 // 1 : reserved for later support 1177 // 2 : don't try again and delete the state file (rendered data can't be 1178 // recovered). 1179 // 3 : try again with the same file (NewPath is ignored). 1180 // 4 : try again with the new path returned in NewPath. 1181 // 1182 // Note that if you choose to specify any of the "don't try again" options, 1183 // and the session happens to be an animation, and it's likely the same 1184 // error will occur again (e.g. invalid output path or something), then 1185 // you may want to call the render cancel API so the user isn't bombarded 1186 // with an error message for each frame of the render. 1187 // 1188 // NB this method is pure virtual. 1189 // 1190 // NOTE: The code to call this method isn't implemented in vfe yet. 1191 virtual int RequestNewOutputPath(int CallCount, const string& Reason, const UCS2String& OldPath, UCS2String& NewPath) = 0; 1192 1193 // Create an instance of the frontend ShelloutProcessing class. this handles creating and 1194 // managing render shellout commands, and typically will need platform-specific implementation. 1195 virtual ShelloutProcessing *CreateShelloutProcessing(POVMS_Object& opts, const string& scene, uint width, uint height) { return new ShelloutProcessing(opts, scene, width, height); } 1196 1197 struct vfeSessionWorker 1198 { 1199 vfeSessionWorker(vfeSession& Parent) : m_Parent(Parent) {} 1200 void operator()() { m_Parent.WorkerThread(); } 1201 vfeSession& m_Parent; 1202 }; 1203 1204 int m_Id; 1205 int m_RenderWidth; 1206 int m_RenderHeight; 1207 int m_RenderErrorCode; 1208 int m_InitializeErrorCode; 1209 int m_LastError; 1210 int m_ConsoleWidth; 1211 int m_PercentComplete; 1212 int m_PixelsRendered; 1213 int m_TotalPixels; 1214 int m_CurrentFrame; 1215 int m_TotalFrames; 1216 bool m_Failed; 1217 bool m_Succeeded; 1218 bool m_HadErrorMessage; 1219 bool m_UsingAlpha; 1220 bool m_RenderingAnimation; 1221 bool m_RealTimeRaytracing; 1222 bool m_ClocklessAnimation; 1223 bool m_HadCriticalError; 1224 bool m_RenderCancelled; 1225 bool m_RenderCancelRequested; 1226 bool m_DontWriteImage; 1227 bool m_OutputToFileSet; 1228 bool m_OptionsSet; 1229 bool m_OptimizeForConsoleOutput; 1230 bool m_PauseWhenDone; 1231 POV_LONG m_StartTime; 1232 unsigned int m_MessageCount; 1233 vfeStatusFlags m_EventMask; 1234 vfeStatusFlags m_StatusFlags; 1235 vfeRenderOptions m_RenderOptions; 1236 1237 static bool m_Initialized; 1238 static vfeSession *m_CurrentSessionTemporaryHack; 1239 shared_ptr<Console> m_Console; 1240 1241 virtual vfeDisplay *DefaultDisplayCreator (unsigned int width, unsigned int height, GammaCurvePtr gamma, vfeSession *session, bool visible); 1242 DisplayCreator m_DisplayCreator; 1243 1244 int m_MaxStatusMessages; 1245 int m_MaxGenericMessages; 1246 int m_MaxConsoleMessages; 1247 GenericQueue m_MessageQueue; 1248 StatusQueue m_StatusQueue; 1249 ConsoleQueue m_ConsoleQueue; 1250 string m_StatusLineMessage; 1251 UCS2String m_OutputFilename; 1252 UCS2String m_InputFilename; 1253 IOPathVector m_ReadPaths; 1254 IOPathVector m_WritePaths; 1255 IOPathVector m_ExcludedPaths; 1256 1257 VirtualFrontEnd *m_Frontend; 1258 State m_BackendState; 1259 1260 boost::mutex m_MessageMutex; 1261 boost::mutex m_SessionMutex; 1262 boost::condition m_SessionEvent; 1263 boost::mutex m_InitializeMutex; 1264 boost::condition m_InitializeEvent; 1265 boost::condition m_ShutdownEvent; 1266 boost::thread *m_WorkerThread; 1267 boost::thread *m_BackendThread; 1268 volatile bool m_WorkerThreadExited; 1269 volatile bool m_BackendThreadExited; 1270 volatile bool m_WorkerThreadShutdownRequest; 1271 1272 boost::mutex m_RequestMutex; 1273 boost::condition m_RequestEvent; 1274 volatile int m_RequestFlag; 1275 volatile int m_RequestResult; 1276 } ; 1277 } 1278 1279 #endif // __VFESESSION_H__