frontengine 1.0.23__tar.gz → 1.0.25__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of frontengine might be problematic. Click here for more details.

Files changed (138) hide show
  1. {frontengine-1.0.23 → frontengine-1.0.25}/PKG-INFO +1 -1
  2. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/pet/pet_setting_ui.py +3 -0
  3. frontengine-1.0.25/frontengine/utils/audio_meter/system_audio_meter.py +136 -0
  4. frontengine-1.0.25/frontengine/worker/__init__.py +0 -0
  5. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine.egg-info/PKG-INFO +1 -1
  6. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine.egg-info/SOURCES.txt +2 -0
  7. {frontengine-1.0.23 → frontengine-1.0.25}/pyproject.toml +1 -1
  8. {frontengine-1.0.23 → frontengine-1.0.25}/LICENSE +0 -0
  9. {frontengine-1.0.23 → frontengine-1.0.25}/README.md +0 -0
  10. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/__init__.py +0 -0
  11. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/__main__.py +0 -0
  12. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/__init__.py +0 -0
  13. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/base_widget.py +0 -0
  14. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/gif/__init__.py +0 -0
  15. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/gif/paint_gif.py +0 -0
  16. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/image/__init__.py +0 -0
  17. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/image/paint_image.py +0 -0
  18. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/load/__init__.py +0 -0
  19. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/load/load_someone_make_ui.py +0 -0
  20. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/overlay_factory.py +0 -0
  21. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/particle/__init__.py +0 -0
  22. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/particle/particle_ui.py +0 -0
  23. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/pet/__init__.py +0 -0
  24. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/pet/desktop_pet.py +0 -0
  25. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/scene/__init__.py +0 -0
  26. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/scene/extend_graphic_scene.py +0 -0
  27. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/scene/extend_graphic_view.py +0 -0
  28. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/scene/scene.py +0 -0
  29. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/sound_player/__init__.py +0 -0
  30. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/sound_player/sound_effect.py +0 -0
  31. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/sound_player/sound_player.py +0 -0
  32. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/text/__init__.py +0 -0
  33. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/text/draw_text.py +0 -0
  34. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/video/__init__.py +0 -0
  35. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/video/video_player.py +0 -0
  36. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/web/__init__.py +0 -0
  37. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/web/webview.py +0 -0
  38. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/show/window_helpers.py +0 -0
  39. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/system_tray/__init__.py +0 -0
  40. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/system_tray/extend_system_tray.py +0 -0
  41. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/__init__.py +0 -0
  42. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/color/__init__.py +0 -0
  43. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/color/global_color.py +0 -0
  44. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/dialog/__init__.py +0 -0
  45. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
  46. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
  47. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/dialog/save_file_dialog.py +0 -0
  48. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/main_ui.py +0 -0
  49. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/menu/__init__.py +0 -0
  50. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/menu/help_menu.py +0 -0
  51. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/menu/how_to_menu.py +0 -0
  52. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/menu/language_menu.py +0 -0
  53. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/menu/preset_menu.py +0 -0
  54. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/menu/settings_menu.py +0 -0
  55. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/__init__.py +0 -0
  56. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/control_center/__init__.py +0 -0
  57. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/control_center/control_center_ui.py +0 -0
  58. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/gif/__init__.py +0 -0
  59. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
  60. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/image/__init__.py +0 -0
  61. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/image/image_setting_ui.py +0 -0
  62. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/particle/__init__.py +0 -0
  63. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
  64. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/pet/__init__.py +0 -0
  65. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/__init__.py +0 -0
  66. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
  67. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/__init__.py +0 -0
  68. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
  69. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
  70. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
  71. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
  72. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
  73. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
  74. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
  75. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
  76. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
  77. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/sound_player/__init__.py +0 -0
  78. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
  79. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/text/__init__.py +0 -0
  80. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/text/text_setting_ui.py +0 -0
  81. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/utils.py +0 -0
  82. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/video/__init__.py +0 -0
  83. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/video/video_setting_ui.py +0 -0
  84. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/web/__init__.py +0 -0
  85. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/ui/page/web/web_setting_ui.py +0 -0
  86. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/user_setting/__init__.py +0 -0
  87. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/user_setting/preset_repository.py +0 -0
  88. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/user_setting/scene_setting.py +0 -0
  89. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/user_setting/user_setting_file.py +0 -0
  90. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/__init__.py +0 -0
  91. {frontengine-1.0.23/frontengine/utils/browser → frontengine-1.0.25/frontengine/utils/audio_meter}/__init__.py +0 -0
  92. {frontengine-1.0.23/frontengine/utils/critical_exit → frontengine-1.0.25/frontengine/utils/browser}/__init__.py +0 -0
  93. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/browser/browser.py +0 -0
  94. {frontengine-1.0.23/frontengine/utils/file → frontengine-1.0.25/frontengine/utils/critical_exit}/__init__.py +0 -0
  95. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
  96. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/critical_exit/critical_exit.py +0 -0
  97. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/critical_exit/win32_vk.py +0 -0
  98. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/exception/__init__.py +0 -0
  99. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/exception/exception_tags.py +0 -0
  100. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/exception/exceptions.py +0 -0
  101. {frontengine-1.0.23/frontengine/utils/hotkey → frontengine-1.0.25/frontengine/utils/file}/__init__.py +0 -0
  102. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/file/open/__init__.py +0 -0
  103. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/file/open/open_file.py +0 -0
  104. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/file/save/__init__.py +0 -0
  105. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/file/save/save_file.py +0 -0
  106. {frontengine-1.0.23/frontengine/utils/json → frontengine-1.0.25/frontengine/utils/hotkey}/__init__.py +0 -0
  107. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/hotkey/hotkey_service.py +0 -0
  108. {frontengine-1.0.23/frontengine/utils/logging → frontengine-1.0.25/frontengine/utils/json}/__init__.py +0 -0
  109. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/json/json_file.py +0 -0
  110. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/json/json_repository.py +0 -0
  111. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/json_format/__init__.py +0 -0
  112. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/json_format/json_process.py +0 -0
  113. {frontengine-1.0.23/frontengine/utils/multi_language → frontengine-1.0.25/frontengine/utils/logging}/__init__.py +0 -0
  114. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/logging/loggin_instance.py +0 -0
  115. {frontengine-1.0.23/frontengine/utils/preset_schedule → frontengine-1.0.25/frontengine/utils/multi_language}/__init__.py +0 -0
  116. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/english.py +0 -0
  117. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/france.py +0 -0
  118. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/germany.py +0 -0
  119. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/italy.py +0 -0
  120. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/language_wrapper.py +0 -0
  121. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/russian.py +0 -0
  122. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/simplified_chinese.py +0 -0
  123. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/multi_language/traditional_chinese.py +0 -0
  124. {frontengine-1.0.23/frontengine/utils/redirect_manager → frontengine-1.0.25/frontengine/utils/preset_schedule}/__init__.py +0 -0
  125. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
  126. {frontengine-1.0.23/frontengine/utils/smart_pause → frontengine-1.0.25/frontengine/utils/redirect_manager}/__init__.py +0 -0
  127. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
  128. {frontengine-1.0.23/frontengine/utils/theme_schedule → frontengine-1.0.25/frontengine/utils/smart_pause}/__init__.py +0 -0
  129. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/smart_pause/smart_pause_service.py +0 -0
  130. {frontengine-1.0.23/frontengine/worker → frontengine-1.0.25/frontengine/utils/theme_schedule}/__init__.py +0 -0
  131. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
  132. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/utils/web_url.py +0 -0
  133. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine/worker/qthread_worker.py +0 -0
  134. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine.egg-info/dependency_links.txt +0 -0
  135. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine.egg-info/entry_points.txt +0 -0
  136. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine.egg-info/requires.txt +0 -0
  137. {frontengine-1.0.23 → frontengine-1.0.25}/frontengine.egg-info/top_level.txt +0 -0
  138. {frontengine-1.0.23 → frontengine-1.0.25}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frontengine
3
- Version: 1.0.23
3
+ Version: 1.0.25
4
4
  Summary: FrontEngine is use-define frontview or only use like screen saver
5
5
  Author-email: JE-Chen <jechenmailman@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/Intergration-Automation-Testing/FrontEngine
@@ -17,6 +17,7 @@ from frontengine.ui.page.utils import (
17
17
  resolve_preferred_monitor,
18
18
  )
19
19
  from frontengine.user_setting.user_setting_file import add_recent_file
20
+ from frontengine.utils.audio_meter.system_audio_meter import system_audio_level
20
21
  from frontengine.utils.logging.loggin_instance import front_engine_logger
21
22
  from frontengine.utils.multi_language.language_wrapper import language_wrapper
22
23
 
@@ -146,6 +147,8 @@ class PetSettingUI(QWidget):
146
147
  )
147
148
  pet.clone_requested.connect(self._spawn_pet)
148
149
  pet.set_peers_provider(lambda me=pet: self._peer_centers(me))
150
+ if self.audio_react_checkbox.isChecked():
151
+ pet.set_audio_level_provider(system_audio_level) # real system output peak meter
149
152
  pet.set_pet_window_flag()
150
153
  self.pet_list.append(pet)
151
154
  pet.show()
@@ -0,0 +1,136 @@
1
+ """
2
+ 以 WASAPI 的 IAudioMeterInformation::GetPeakValue 讀取「預設輸出裝置」的
3
+ 峰值電表 (0~1)。這只是讀取電表數值,不擷取或錄製任何音訊內容(隱私友善),
4
+ 僅 Windows 有效,任何失敗都退化為 None。
5
+
6
+ Read the default output device's peak meter (0..1) via WASAPI's
7
+ IAudioMeterInformation::GetPeakValue. This only reads a meter value — it does
8
+ NOT capture or record any audio content. Windows only; degrades to None.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import sys
13
+ import uuid
14
+ from typing import Optional
15
+
16
+ from frontengine.utils.logging.loggin_instance import front_engine_logger
17
+
18
+ # WASAPI / Core Audio identifiers
19
+ _CLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
20
+ _IID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
21
+ _IID_IAudioMeterInformation = "{C02216F6-8C67-4B5B-9D00-D008E73E0064}"
22
+ _CLSCTX_ALL = 23
23
+ _E_RENDER = 0 # audio output
24
+ _E_CONSOLE = 0 # default role
25
+
26
+
27
+ class SystemAudioMeter:
28
+ """讀取系統輸出峰值電表;建立失敗或非 Windows 時 level() 回傳 None。"""
29
+
30
+ def __init__(self) -> None:
31
+ self._ok = False
32
+ self._meter = None
33
+ self._device = None
34
+ self._enumerator = None
35
+ self._get_peak = None
36
+ self._byref = None
37
+ self._c_float = None
38
+ self._release_method = None
39
+ if sys.platform == "win32":
40
+ try:
41
+ self._init()
42
+ self._ok = True
43
+ except Exception as error: # pragma: no cover - COM boundary
44
+ front_engine_logger.warning(f"[SystemAudioMeter] init failed: {error!r}")
45
+ self._release_all()
46
+
47
+ # --- COM plumbing -------------------------------------------------
48
+ def _init(self) -> None:
49
+ import ctypes
50
+ from ctypes import POINTER, byref, c_float, c_void_p, c_ulong, HRESULT
51
+ from ctypes.wintypes import DWORD
52
+
53
+ class _GUID(ctypes.Structure):
54
+ _fields_ = [
55
+ ("Data1", ctypes.c_uint32),
56
+ ("Data2", ctypes.c_uint16),
57
+ ("Data3", ctypes.c_uint16),
58
+ ("Data4", ctypes.c_uint8 * 8),
59
+ ]
60
+
61
+ def guid(text: str) -> "_GUID":
62
+ value = _GUID()
63
+ ctypes.memmove(byref(value), uuid.UUID(text).bytes_le, ctypes.sizeof(value))
64
+ return value
65
+
66
+ def method(iface, index, restype, argtypes):
67
+ vtable = ctypes.cast(iface, POINTER(POINTER(c_void_p)))
68
+ func_address = vtable[0][index]
69
+ proto = ctypes.WINFUNCTYPE(restype, c_void_p, *argtypes)
70
+ return proto(func_address)
71
+
72
+ ole32 = ctypes.windll.ole32
73
+ ole32.CoInitialize(None) # S_FALSE if already initialised; harmless
74
+
75
+ enumerator = c_void_p()
76
+ clsid = guid(_CLSID_MMDeviceEnumerator)
77
+ iid_enum = guid(_IID_IMMDeviceEnumerator)
78
+ if ole32.CoCreateInstance(byref(clsid), None, _CLSCTX_ALL, byref(iid_enum), byref(enumerator)) != 0 \
79
+ or not enumerator.value:
80
+ raise OSError("CoCreateInstance(MMDeviceEnumerator) failed")
81
+ self._enumerator = enumerator
82
+
83
+ device = c_void_p()
84
+ get_default = method(enumerator, 4, HRESULT, [DWORD, DWORD, POINTER(c_void_p)])
85
+ if get_default(enumerator, _E_RENDER, _E_CONSOLE, byref(device)) != 0 or not device.value:
86
+ raise OSError("GetDefaultAudioEndpoint failed")
87
+ self._device = device
88
+
89
+ meter = c_void_p()
90
+ iid_meter = guid(_IID_IAudioMeterInformation)
91
+ activate = method(device, 3, HRESULT, [POINTER(_GUID), DWORD, c_void_p, POINTER(c_void_p)])
92
+ if activate(device, byref(iid_meter), _CLSCTX_ALL, None, byref(meter)) != 0 or not meter.value:
93
+ raise OSError("Activate(IAudioMeterInformation) failed")
94
+ self._meter = meter
95
+
96
+ self._get_peak = method(meter, 3, HRESULT, [POINTER(c_float)])
97
+ self._byref = byref
98
+ self._c_float = c_float
99
+ self._release_method = lambda iface: method(iface, 2, c_ulong, [])
100
+
101
+ def level(self) -> Optional[float]:
102
+ """回傳目前輸出峰值 0~1,或 None。"""
103
+ if not self._ok or self._meter is None or self._get_peak is None:
104
+ return None
105
+ try:
106
+ peak = self._c_float()
107
+ if self._get_peak(self._meter, self._byref(peak)) != 0:
108
+ return None
109
+ return max(0.0, min(1.0, float(peak.value)))
110
+ except Exception: # pragma: no cover - COM boundary
111
+ return None
112
+
113
+ def _release_all(self) -> None:
114
+ for iface in (self._meter, self._device, self._enumerator):
115
+ if iface is not None and getattr(iface, "value", None) and self._release_method is not None:
116
+ try:
117
+ self._release_method(iface)(iface)
118
+ except Exception as error: # pragma: no cover - COM boundary
119
+ # 釋放個別介面失敗不影響清理流程,記錄後繼續。
120
+ # A single interface failing to release must not abort cleanup.
121
+ front_engine_logger.debug(f"[SystemAudioMeter] release failed: {error!r}")
122
+ self._meter = self._device = self._enumerator = None
123
+ self._ok = False
124
+
125
+
126
+ _meter_singleton: Optional[SystemAudioMeter] = None
127
+
128
+
129
+ def system_audio_level() -> Optional[float]:
130
+ """便利函式:以單例電表回傳目前系統輸出峰值 0~1,或 None。"""
131
+ global _meter_singleton
132
+ if sys.platform != "win32":
133
+ return None
134
+ if _meter_singleton is None:
135
+ _meter_singleton = SystemAudioMeter()
136
+ return _meter_singleton.level()
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frontengine
3
- Version: 1.0.23
3
+ Version: 1.0.25
4
4
  Summary: FrontEngine is use-define frontview or only use like screen saver
5
5
  Author-email: JE-Chen <jechenmailman@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/Intergration-Automation-Testing/FrontEngine
@@ -90,6 +90,8 @@ frontengine/user_setting/scene_setting.py
90
90
  frontengine/user_setting/user_setting_file.py
91
91
  frontengine/utils/__init__.py
92
92
  frontengine/utils/web_url.py
93
+ frontengine/utils/audio_meter/__init__.py
94
+ frontengine/utils/audio_meter/system_audio_meter.py
93
95
  frontengine/utils/browser/__init__.py
94
96
  frontengine/utils/browser/browser.py
95
97
  frontengine/utils/critical_exit/__init__.py
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "frontengine"
9
- version = "1.0.23"
9
+ version = "1.0.25"
10
10
  authors = [
11
11
  { name = "JE-Chen", email = "jechenmailman@gmail.com" },
12
12
  ]
File without changes
File without changes
File without changes