/ vfe / vfesession.h
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__