| 1 | /**************************************************************************/ |
| 2 | /* os.h */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #ifndef OS_H |
| 32 | #define OS_H |
| 33 | |
| 34 | #include "core/config/engine.h" |
| 35 | #include "core/io/image.h" |
| 36 | #include "core/io/logger.h" |
| 37 | #include "core/io/remote_filesystem_client.h" |
| 38 | #include "core/os/time_enums.h" |
| 39 | #include "core/string/ustring.h" |
| 40 | #include "core/templates/list.h" |
| 41 | #include "core/templates/vector.h" |
| 42 | |
| 43 | #include <stdarg.h> |
| 44 | #include <stdlib.h> |
| 45 | |
| 46 | class OS { |
| 47 | static OS *singleton; |
| 48 | static uint64_t target_ticks; |
| 49 | String _execpath; |
| 50 | List<String> _cmdline; |
| 51 | List<String> _user_args; |
| 52 | bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. |
| 53 | bool low_processor_usage_mode = false; |
| 54 | int low_processor_usage_mode_sleep_usec = 10000; |
| 55 | bool _delta_smoothing_enabled = false; |
| 56 | bool _verbose_stdout = false; |
| 57 | bool _debug_stdout = false; |
| 58 | String _local_clipboard; |
| 59 | int _exit_code = EXIT_FAILURE; // unexpected exit is marked as failure |
| 60 | bool _allow_hidpi = false; |
| 61 | bool _allow_layered = false; |
| 62 | bool _stdout_enabled = true; |
| 63 | bool _stderr_enabled = true; |
| 64 | bool _writing_movie = false; |
| 65 | |
| 66 | CompositeLogger *_logger = nullptr; |
| 67 | |
| 68 | bool restart_on_exit = false; |
| 69 | List<String> restart_commandline; |
| 70 | |
| 71 | // for the user interface we keep a record of the current display driver |
| 72 | // so we can retrieve the rendering drivers available |
| 73 | int _display_driver_id = -1; |
| 74 | String _current_rendering_driver_name; |
| 75 | String _current_rendering_method; |
| 76 | |
| 77 | RemoteFilesystemClient default_rfs; |
| 78 | |
| 79 | // For tracking benchmark data |
| 80 | bool use_benchmark = false; |
| 81 | String benchmark_file; |
| 82 | HashMap<String, uint64_t> start_benchmark_from; |
| 83 | Dictionary startup_benchmark_json; |
| 84 | |
| 85 | protected: |
| 86 | void _set_logger(CompositeLogger *p_logger); |
| 87 | |
| 88 | public: |
| 89 | typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection); |
| 90 | typedef bool (*HasServerFeatureCallback)(const String &p_feature); |
| 91 | |
| 92 | enum RenderThreadMode { |
| 93 | RENDER_THREAD_UNSAFE, |
| 94 | RENDER_THREAD_SAFE, |
| 95 | RENDER_SEPARATE_THREAD |
| 96 | }; |
| 97 | |
| 98 | protected: |
| 99 | friend class Main; |
| 100 | // Needed by tests to setup command-line args. |
| 101 | friend int test_main(int argc, char *argv[]); |
| 102 | |
| 103 | HasServerFeatureCallback has_server_feature_callback = nullptr; |
| 104 | RenderThreadMode _render_thread_mode = RENDER_THREAD_SAFE; |
| 105 | |
| 106 | // Functions used by Main to initialize/deinitialize the OS. |
| 107 | void add_logger(Logger *p_logger); |
| 108 | |
| 109 | virtual void initialize() = 0; |
| 110 | virtual void initialize_joypads() = 0; |
| 111 | |
| 112 | void set_current_rendering_driver_name(String p_driver_name) { _current_rendering_driver_name = p_driver_name; } |
| 113 | void set_current_rendering_method(String p_name) { _current_rendering_method = p_name; } |
| 114 | |
| 115 | void set_display_driver_id(int p_display_driver_id) { _display_driver_id = p_display_driver_id; } |
| 116 | |
| 117 | virtual void set_main_loop(MainLoop *p_main_loop) = 0; |
| 118 | virtual void delete_main_loop() = 0; |
| 119 | |
| 120 | virtual void finalize() = 0; |
| 121 | virtual void finalize_core() = 0; |
| 122 | |
| 123 | virtual void set_cmdline(const char *p_execpath, const List<String> &p_args, const List<String> &p_user_args); |
| 124 | |
| 125 | virtual bool _check_internal_feature_support(const String &p_feature) = 0; |
| 126 | |
| 127 | public: |
| 128 | typedef int64_t ProcessID; |
| 129 | |
| 130 | static OS *get_singleton(); |
| 131 | |
| 132 | String get_current_rendering_driver_name() const { return _current_rendering_driver_name; } |
| 133 | String get_current_rendering_method() const { return _current_rendering_method; } |
| 134 | |
| 135 | int get_display_driver_id() const { return _display_driver_id; } |
| 136 | |
| 137 | virtual Vector<String> get_video_adapter_driver_info() const = 0; |
| 138 | |
| 139 | void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, Logger::ErrorType p_type = Logger::ERR_ERROR); |
| 140 | void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; |
| 141 | void print_rich(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; |
| 142 | void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; |
| 143 | |
| 144 | virtual String get_stdin_string() = 0; |
| 145 | |
| 146 | virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) = 0; // Should return cryptographically-safe random bytes. |
| 147 | virtual String get_system_ca_certificates() { return "" ; } // Concatenated certificates in PEM format. |
| 148 | |
| 149 | virtual PackedStringArray get_connected_midi_inputs(); |
| 150 | virtual void open_midi_inputs(); |
| 151 | virtual void close_midi_inputs(); |
| 152 | |
| 153 | virtual void alert(const String &p_alert, const String &p_title = "ALERT!" ); |
| 154 | |
| 155 | virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) { return ERR_UNAVAILABLE; } |
| 156 | virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; } |
| 157 | virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; } |
| 158 | |
| 159 | virtual void set_low_processor_usage_mode(bool p_enabled); |
| 160 | virtual bool is_in_low_processor_usage_mode() const; |
| 161 | virtual void set_low_processor_usage_mode_sleep_usec(int p_usec); |
| 162 | virtual int get_low_processor_usage_mode_sleep_usec() const; |
| 163 | |
| 164 | void set_delta_smoothing(bool p_enabled); |
| 165 | bool is_delta_smoothing_enabled() const; |
| 166 | |
| 167 | virtual Vector<String> get_system_fonts() const { return Vector<String>(); }; |
| 168 | virtual String get_system_font_path(const String &p_font_name, int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return String(); }; |
| 169 | virtual Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const { return Vector<String>(); }; |
| 170 | virtual String get_executable_path() const; |
| 171 | virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) = 0; |
| 172 | virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) = 0; |
| 173 | virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) { return create_process(get_executable_path(), p_arguments, r_child_id); }; |
| 174 | virtual Error kill(const ProcessID &p_pid) = 0; |
| 175 | virtual int get_process_id() const; |
| 176 | virtual bool is_process_running(const ProcessID &p_pid) const = 0; |
| 177 | virtual void vibrate_handheld(int p_duration_ms = 500) {} |
| 178 | |
| 179 | virtual Error shell_open(String p_uri); |
| 180 | virtual Error shell_show_in_file_manager(String p_path, bool p_open_folder = true); |
| 181 | virtual Error set_cwd(const String &p_cwd); |
| 182 | |
| 183 | virtual bool has_environment(const String &p_var) const = 0; |
| 184 | virtual String get_environment(const String &p_var) const = 0; |
| 185 | virtual void set_environment(const String &p_var, const String &p_value) const = 0; |
| 186 | virtual void unset_environment(const String &p_var) const = 0; |
| 187 | |
| 188 | virtual String get_name() const = 0; |
| 189 | virtual String get_identifier() const; |
| 190 | virtual String get_distribution_name() const = 0; |
| 191 | virtual String get_version() const = 0; |
| 192 | virtual List<String> get_cmdline_args() const { return _cmdline; } |
| 193 | virtual List<String> get_cmdline_user_args() const { return _user_args; } |
| 194 | virtual List<String> get_cmdline_platform_args() const { return List<String>(); } |
| 195 | virtual String get_model_name() const; |
| 196 | |
| 197 | bool is_layered_allowed() const { return _allow_layered; } |
| 198 | bool is_hidpi_allowed() const { return _allow_hidpi; } |
| 199 | |
| 200 | void ensure_user_data_dir(); |
| 201 | |
| 202 | virtual MainLoop *get_main_loop() const = 0; |
| 203 | |
| 204 | virtual void yield(); |
| 205 | |
| 206 | struct DateTime { |
| 207 | int64_t year; |
| 208 | Month month; |
| 209 | uint8_t day; |
| 210 | Weekday weekday; |
| 211 | uint8_t hour; |
| 212 | uint8_t minute; |
| 213 | uint8_t second; |
| 214 | bool dst; |
| 215 | }; |
| 216 | |
| 217 | struct TimeZoneInfo { |
| 218 | int bias; |
| 219 | String name; |
| 220 | }; |
| 221 | |
| 222 | virtual DateTime get_datetime(bool utc = false) const = 0; |
| 223 | virtual TimeZoneInfo get_time_zone_info() const = 0; |
| 224 | virtual double get_unix_time() const; |
| 225 | |
| 226 | virtual void delay_usec(uint32_t p_usec) const = 0; |
| 227 | virtual void add_frame_delay(bool p_can_draw); |
| 228 | |
| 229 | virtual uint64_t get_ticks_usec() const = 0; |
| 230 | uint64_t get_ticks_msec() const; |
| 231 | |
| 232 | virtual bool is_userfs_persistent() const { return true; } |
| 233 | |
| 234 | bool is_stdout_verbose() const; |
| 235 | bool is_stdout_debug_enabled() const; |
| 236 | |
| 237 | bool is_stdout_enabled() const; |
| 238 | bool is_stderr_enabled() const; |
| 239 | void set_stdout_enabled(bool p_enabled); |
| 240 | void set_stderr_enabled(bool p_enabled); |
| 241 | |
| 242 | virtual void disable_crash_handler() {} |
| 243 | virtual bool is_disable_crash_handler() const { return false; } |
| 244 | virtual void initialize_debugging() {} |
| 245 | |
| 246 | virtual uint64_t get_static_memory_usage() const; |
| 247 | virtual uint64_t get_static_memory_peak_usage() const; |
| 248 | virtual Dictionary get_memory_info() const; |
| 249 | |
| 250 | RenderThreadMode get_render_thread_mode() const { return _render_thread_mode; } |
| 251 | |
| 252 | virtual String get_locale() const; |
| 253 | String get_locale_language() const; |
| 254 | |
| 255 | virtual uint64_t get_embedded_pck_offset() const; |
| 256 | |
| 257 | String get_safe_dir_name(const String &p_dir_name, bool p_allow_paths = false) const; |
| 258 | virtual String get_godot_dir_name() const; |
| 259 | |
| 260 | virtual String get_data_path() const; |
| 261 | virtual String get_config_path() const; |
| 262 | virtual String get_cache_path() const; |
| 263 | virtual String get_bundle_resource_dir() const; |
| 264 | virtual String get_bundle_icon_path() const; |
| 265 | |
| 266 | virtual String get_user_data_dir() const; |
| 267 | virtual String get_resource_dir() const; |
| 268 | |
| 269 | enum SystemDir { |
| 270 | SYSTEM_DIR_DESKTOP, |
| 271 | SYSTEM_DIR_DCIM, |
| 272 | SYSTEM_DIR_DOCUMENTS, |
| 273 | SYSTEM_DIR_DOWNLOADS, |
| 274 | SYSTEM_DIR_MOVIES, |
| 275 | SYSTEM_DIR_MUSIC, |
| 276 | SYSTEM_DIR_PICTURES, |
| 277 | SYSTEM_DIR_RINGTONES, |
| 278 | }; |
| 279 | |
| 280 | virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const; |
| 281 | |
| 282 | virtual Error move_to_trash(const String &p_path) { return FAILED; } |
| 283 | |
| 284 | virtual int get_exit_code() const; |
| 285 | // `set_exit_code` should only be used from `SceneTree` (or from a similar |
| 286 | // level, e.g. from the `Main::start` if leaving without creating a `SceneTree`). |
| 287 | // For other components, `SceneTree.quit()` should be used instead. |
| 288 | virtual void set_exit_code(int p_code); |
| 289 | |
| 290 | virtual int get_processor_count() const; |
| 291 | virtual String get_processor_name() const; |
| 292 | virtual int get_default_thread_pool_size() const { return get_processor_count(); } |
| 293 | |
| 294 | virtual String get_unique_id() const; |
| 295 | |
| 296 | bool has_feature(const String &p_feature); |
| 297 | |
| 298 | virtual bool is_sandboxed() const; |
| 299 | |
| 300 | void set_has_server_feature_callback(HasServerFeatureCallback p_callback); |
| 301 | |
| 302 | void set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments); |
| 303 | bool is_restart_on_exit_set() const; |
| 304 | List<String> get_restart_on_exit_arguments() const; |
| 305 | |
| 306 | virtual bool request_permission(const String &p_name) { return true; } |
| 307 | virtual bool request_permissions() { return true; } |
| 308 | virtual Vector<String> get_granted_permissions() const { return Vector<String>(); } |
| 309 | virtual void revoke_granted_permissions() {} |
| 310 | |
| 311 | // For recording / measuring benchmark data. Only enabled with tools |
| 312 | void set_use_benchmark(bool p_use_benchmark); |
| 313 | bool is_use_benchmark_set(); |
| 314 | void set_benchmark_file(const String &p_benchmark_file); |
| 315 | String get_benchmark_file(); |
| 316 | virtual void benchmark_begin_measure(const String &p_what); |
| 317 | virtual void benchmark_end_measure(const String &p_what); |
| 318 | virtual void benchmark_dump(); |
| 319 | |
| 320 | virtual void process_and_drop_events() {} |
| 321 | |
| 322 | virtual Error setup_remote_filesystem(const String &p_server_host, int p_port, const String &p_password, String &r_project_path); |
| 323 | |
| 324 | enum PreferredTextureFormat { |
| 325 | PREFERRED_TEXTURE_FORMAT_S3TC_BPTC, |
| 326 | PREFERRED_TEXTURE_FORMAT_ETC2_ASTC |
| 327 | }; |
| 328 | |
| 329 | virtual PreferredTextureFormat get_preferred_texture_format() const; |
| 330 | |
| 331 | // Load GDExtensions specific to this platform. |
| 332 | // This is invoked by the GDExtensionManager after loading GDExtensions specified by the project. |
| 333 | virtual void load_platform_gdextensions() const {} |
| 334 | |
| 335 | OS(); |
| 336 | virtual ~OS(); |
| 337 | }; |
| 338 | |
| 339 | #endif // OS_H |
| 340 | |