pumaguard 20.post232__py3-none-any.whl → 20.post240__py3-none-any.whl
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.
- pumaguard/presets.py +25 -0
- pumaguard/pumaguard-ui/.last_build_id +1 -1
- pumaguard/pumaguard-ui/assets/AssetManifest.bin +1 -1
- pumaguard/pumaguard-ui/assets/AssetManifest.bin.json +1 -1
- pumaguard/pumaguard-ui/assets/FontManifest.json +1 -1
- pumaguard/pumaguard-ui/assets/NOTICES +213 -0
- pumaguard/pumaguard-ui/assets/fonts/MaterialIcons-Regular.otf +0 -0
- pumaguard/pumaguard-ui/assets/fonts/Roboto-Bold.ttf +0 -0
- pumaguard/pumaguard-ui/assets/fonts/Roboto-Light.ttf +0 -0
- pumaguard/pumaguard-ui/assets/fonts/Roboto-Medium.ttf +0 -0
- pumaguard/pumaguard-ui/assets/fonts/Roboto-Regular.ttf +0 -0
- pumaguard/pumaguard-ui/assets/fonts/RobotoMono-Bold.ttf +0 -0
- pumaguard/pumaguard-ui/assets/fonts/RobotoMono-Medium.ttf +0 -0
- pumaguard/pumaguard-ui/assets/fonts/RobotoMono-Regular.ttf +0 -0
- pumaguard/pumaguard-ui/flutter_bootstrap.js +1 -5
- pumaguard/pumaguard-ui/flutter_service_worker.js +0 -207
- pumaguard/pumaguard-ui/index.html +0 -22
- pumaguard/pumaguard-ui/main.dart.js +55083 -52886
- pumaguard/server.py +1 -1
- pumaguard/sound.py +138 -5
- pumaguard/web_routes/settings.py +80 -6
- {pumaguard-20.post232.dist-info → pumaguard-20.post240.dist-info}/METADATA +1 -1
- {pumaguard-20.post232.dist-info → pumaguard-20.post240.dist-info}/RECORD +27 -20
- {pumaguard-20.post232.dist-info → pumaguard-20.post240.dist-info}/WHEEL +0 -0
- {pumaguard-20.post232.dist-info → pumaguard-20.post240.dist-info}/entry_points.txt +0 -0
- {pumaguard-20.post232.dist-info → pumaguard-20.post240.dist-info}/licenses/LICENSE +0 -0
- {pumaguard-20.post232.dist-info → pumaguard-20.post240.dist-info}/top_level.txt +0 -0
pumaguard/server.py
CHANGED
|
@@ -272,7 +272,7 @@ class FolderObserver:
|
|
|
272
272
|
sound_file_path = os.path.join(
|
|
273
273
|
self.presets.sound_path, self.presets.deterrent_sound_file
|
|
274
274
|
)
|
|
275
|
-
playsound(sound_file_path)
|
|
275
|
+
playsound(sound_file_path, self.presets.volume)
|
|
276
276
|
# Move original file into classification folder
|
|
277
277
|
try:
|
|
278
278
|
dest_root = (
|
pumaguard/sound.py
CHANGED
|
@@ -2,22 +2,155 @@
|
|
|
2
2
|
Sounds
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import logging
|
|
5
6
|
import subprocess
|
|
6
7
|
import sys
|
|
8
|
+
import threading
|
|
9
|
+
from typing import Optional
|
|
7
10
|
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
# Global variable to track the current playing process
|
|
14
|
+
_current_process: Optional[subprocess.Popen] = None
|
|
15
|
+
_process_lock = threading.Lock()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def playsound(soundfile: str, volume: int = 80, blocking: bool = True):
|
|
10
19
|
"""
|
|
11
|
-
Play a sound file.
|
|
20
|
+
Play a sound file with specified volume.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
soundfile: Path to the sound file to play
|
|
24
|
+
volume: Volume level from 0-100 (default: 80)
|
|
25
|
+
blocking: If True, wait for sound to finish. If False, return
|
|
26
|
+
immediately (default: True)
|
|
12
27
|
"""
|
|
28
|
+
global _current_process # pylint: disable=global-statement
|
|
29
|
+
|
|
30
|
+
logger.info(
|
|
31
|
+
"playsound called: file=%s, volume=%d, blocking=%s",
|
|
32
|
+
soundfile,
|
|
33
|
+
volume,
|
|
34
|
+
blocking,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# mpg123 -f flag scales output samples (soft gain)
|
|
38
|
+
# Default/normal is 32768 (100%)
|
|
39
|
+
# Valid range: 0 to much higher than 32768
|
|
40
|
+
# Convert 0-100 percentage to mpg123 scale:
|
|
41
|
+
# 0% = 0 (muted), 100% = 32768 (normal), 200% = 65536 (double)
|
|
42
|
+
# Linear scaling: mpg123_volume = (volume / 100) * 32768
|
|
43
|
+
mpg123_volume = int((volume / 100.0) * 32768)
|
|
44
|
+
|
|
45
|
+
logger.debug(
|
|
46
|
+
"Volume conversion: %d%% -> mpg123 scale %d", volume, mpg123_volume
|
|
47
|
+
)
|
|
48
|
+
|
|
13
49
|
try:
|
|
14
|
-
|
|
15
|
-
|
|
50
|
+
with _process_lock:
|
|
51
|
+
# Stop any currently playing sound
|
|
52
|
+
if _current_process is not None:
|
|
53
|
+
try:
|
|
54
|
+
_current_process.terminate()
|
|
55
|
+
_current_process.wait(timeout=1)
|
|
56
|
+
except (subprocess.TimeoutExpired, ProcessLookupError):
|
|
57
|
+
pass
|
|
58
|
+
_current_process = None
|
|
59
|
+
|
|
60
|
+
# Start new process
|
|
61
|
+
# pylint: disable=consider-using-with
|
|
62
|
+
cmd = ["mpg123", "-o", "alsa", "-f", str(mpg123_volume), soundfile]
|
|
63
|
+
logger.info("Executing command: %s", " ".join(cmd))
|
|
64
|
+
|
|
65
|
+
_current_process = subprocess.Popen(
|
|
66
|
+
cmd,
|
|
67
|
+
stdout=subprocess.DEVNULL,
|
|
68
|
+
stderr=subprocess.DEVNULL,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
logger.info(
|
|
72
|
+
"Sound playback started, PID: %d", _current_process.pid
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if blocking:
|
|
76
|
+
# Wait for completion
|
|
77
|
+
_current_process.wait()
|
|
78
|
+
_current_process = None
|
|
79
|
+
|
|
80
|
+
except subprocess.SubprocessError as e:
|
|
81
|
+
logger.error("Error playing soundfile %s: %s", soundfile, e)
|
|
16
82
|
print(f"Error playing soundfile {soundfile}: {e}")
|
|
83
|
+
with _process_lock:
|
|
84
|
+
_current_process = None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def stop_sound():
|
|
88
|
+
"""
|
|
89
|
+
Stop any currently playing sound.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
bool: True if a sound was stopped, False if nothing was playing
|
|
93
|
+
"""
|
|
94
|
+
global _current_process # pylint: disable=global-statement
|
|
95
|
+
|
|
96
|
+
with _process_lock:
|
|
97
|
+
if _current_process is not None:
|
|
98
|
+
try:
|
|
99
|
+
logger.info(
|
|
100
|
+
"Stopping sound playback, PID: %d", _current_process.pid
|
|
101
|
+
)
|
|
102
|
+
_current_process.terminate()
|
|
103
|
+
_current_process.wait(timeout=1)
|
|
104
|
+
logger.info("Sound playback stopped successfully")
|
|
105
|
+
return True
|
|
106
|
+
except (subprocess.TimeoutExpired, ProcessLookupError):
|
|
107
|
+
try:
|
|
108
|
+
_current_process.kill()
|
|
109
|
+
_current_process.wait(timeout=1)
|
|
110
|
+
except (subprocess.TimeoutExpired, ProcessLookupError):
|
|
111
|
+
pass
|
|
112
|
+
return True
|
|
113
|
+
finally:
|
|
114
|
+
_current_process = None
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def is_playing():
|
|
119
|
+
"""
|
|
120
|
+
Check if a sound is currently playing.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
bool: True if a sound is currently playing, False otherwise
|
|
124
|
+
"""
|
|
125
|
+
global _current_process # pylint: disable=global-statement
|
|
126
|
+
|
|
127
|
+
with _process_lock:
|
|
128
|
+
if _current_process is not None:
|
|
129
|
+
# Check if process is still running
|
|
130
|
+
if _current_process.poll() is None:
|
|
131
|
+
return True
|
|
132
|
+
# Process finished, clean up
|
|
133
|
+
_current_process = None
|
|
134
|
+
return False
|
|
17
135
|
|
|
18
136
|
|
|
19
137
|
def main():
|
|
20
138
|
"""
|
|
21
139
|
Main entry point.
|
|
22
140
|
"""
|
|
23
|
-
|
|
141
|
+
if len(sys.argv) < 2:
|
|
142
|
+
print("Usage: pumaguard-sound <soundfile> [volume]")
|
|
143
|
+
sys.exit(1)
|
|
144
|
+
|
|
145
|
+
volume = 80
|
|
146
|
+
if len(sys.argv) >= 3:
|
|
147
|
+
try:
|
|
148
|
+
volume = int(sys.argv[2])
|
|
149
|
+
if volume < 0 or volume > 100:
|
|
150
|
+
print("Volume must be between 0 and 100")
|
|
151
|
+
sys.exit(1)
|
|
152
|
+
except ValueError:
|
|
153
|
+
print("Volume must be an integer")
|
|
154
|
+
sys.exit(1)
|
|
155
|
+
|
|
156
|
+
playsound(sys.argv[1], volume)
|
pumaguard/web_routes/settings.py
CHANGED
|
@@ -26,7 +26,9 @@ from pumaguard.model_downloader import (
|
|
|
26
26
|
verify_file_checksum,
|
|
27
27
|
)
|
|
28
28
|
from pumaguard.sound import (
|
|
29
|
+
is_playing,
|
|
29
30
|
playsound,
|
|
31
|
+
stop_sound,
|
|
30
32
|
)
|
|
31
33
|
|
|
32
34
|
if TYPE_CHECKING:
|
|
@@ -64,6 +66,8 @@ def register_settings_routes(app: "Flask", webui: "WebUI") -> None:
|
|
|
64
66
|
"deterrent-sound-file",
|
|
65
67
|
"file-stabilization-extra-wait",
|
|
66
68
|
"play-sound",
|
|
69
|
+
"volume",
|
|
70
|
+
"camera-url",
|
|
67
71
|
]
|
|
68
72
|
|
|
69
73
|
if len(data) == 0:
|
|
@@ -71,9 +75,18 @@ def register_settings_routes(app: "Flask", webui: "WebUI") -> None:
|
|
|
71
75
|
|
|
72
76
|
for key, value in data.items():
|
|
73
77
|
if key in allowed_settings:
|
|
74
|
-
logger.
|
|
78
|
+
logger.info(
|
|
79
|
+
"Updating setting %s with value %s", key, value
|
|
80
|
+
)
|
|
75
81
|
attr_name = key.replace("-", "_").replace("YOLO_", "yolo_")
|
|
76
82
|
setattr(webui.presets, attr_name, value)
|
|
83
|
+
# Log verification of volume setting
|
|
84
|
+
if key == "volume":
|
|
85
|
+
logger.info(
|
|
86
|
+
"Volume setting updated to %d, verified: %d",
|
|
87
|
+
value,
|
|
88
|
+
webui.presets.volume,
|
|
89
|
+
)
|
|
77
90
|
else:
|
|
78
91
|
logger.debug("Skipping unknown/read-only setting: %s", key)
|
|
79
92
|
|
|
@@ -82,7 +95,11 @@ def register_settings_routes(app: "Flask", webui: "WebUI") -> None:
|
|
|
82
95
|
settings_dict = dict(webui.presets)
|
|
83
96
|
with open(filepath, "w", encoding="utf-8") as f:
|
|
84
97
|
yaml.dump(settings_dict, f, default_flow_style=False)
|
|
85
|
-
logger.info(
|
|
98
|
+
logger.info(
|
|
99
|
+
"Settings updated and saved to %s (volume: %d)",
|
|
100
|
+
filepath,
|
|
101
|
+
webui.presets.volume,
|
|
102
|
+
)
|
|
86
103
|
except YAMLError:
|
|
87
104
|
logger.exception("Error saving settings")
|
|
88
105
|
return (
|
|
@@ -151,19 +168,65 @@ def register_settings_routes(app: "Flask", webui: "WebUI") -> None:
|
|
|
151
168
|
404,
|
|
152
169
|
)
|
|
153
170
|
|
|
154
|
-
# Play the sound
|
|
155
|
-
|
|
156
|
-
|
|
171
|
+
# Play the sound with configured volume (non-blocking)
|
|
172
|
+
volume = webui.presets.volume
|
|
173
|
+
logger.info(
|
|
174
|
+
"Testing sound playback: file=%s, volume=%d",
|
|
175
|
+
sound_file_path,
|
|
176
|
+
volume,
|
|
177
|
+
)
|
|
178
|
+
logger.debug(
|
|
179
|
+
"Current presets.volume value before playsound: %d",
|
|
180
|
+
webui.presets.volume,
|
|
181
|
+
)
|
|
182
|
+
playsound(sound_file_path, volume, blocking=False)
|
|
157
183
|
return jsonify(
|
|
158
184
|
{
|
|
159
185
|
"success": True,
|
|
160
|
-
"message": f"Sound
|
|
186
|
+
"message": f"Sound started: {sound_file}",
|
|
161
187
|
}
|
|
162
188
|
)
|
|
163
189
|
except Exception as e: # pylint: disable=broad-except
|
|
164
190
|
logger.exception("Error testing sound")
|
|
165
191
|
return jsonify({"error": str(e)}), 500
|
|
166
192
|
|
|
193
|
+
@app.route("/api/settings/stop-sound", methods=["POST"])
|
|
194
|
+
def stop_test_sound():
|
|
195
|
+
"""Stop the currently playing test sound."""
|
|
196
|
+
try:
|
|
197
|
+
stopped = stop_sound()
|
|
198
|
+
if stopped:
|
|
199
|
+
logger.info("Sound playback stopped")
|
|
200
|
+
return jsonify(
|
|
201
|
+
{
|
|
202
|
+
"success": True,
|
|
203
|
+
"message": "Sound stopped",
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
return jsonify(
|
|
207
|
+
{
|
|
208
|
+
"success": True,
|
|
209
|
+
"message": "No sound was playing",
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
except Exception as e: # pylint: disable=broad-except
|
|
213
|
+
logger.exception("Error stopping sound")
|
|
214
|
+
return jsonify({"error": str(e)}), 500
|
|
215
|
+
|
|
216
|
+
@app.route("/api/settings/sound-status", methods=["GET"])
|
|
217
|
+
def get_sound_status():
|
|
218
|
+
"""Check if a sound is currently playing."""
|
|
219
|
+
try:
|
|
220
|
+
playing = is_playing()
|
|
221
|
+
return jsonify(
|
|
222
|
+
{
|
|
223
|
+
"playing": playing,
|
|
224
|
+
}
|
|
225
|
+
)
|
|
226
|
+
except Exception as e: # pylint: disable=broad-except
|
|
227
|
+
logger.exception("Error checking sound status")
|
|
228
|
+
return jsonify({"error": str(e)}), 500
|
|
229
|
+
|
|
167
230
|
@app.route("/api/models/available", methods=["GET"])
|
|
168
231
|
def get_available_models():
|
|
169
232
|
"""Get list of available models with cache status.
|
|
@@ -261,3 +324,14 @@ def register_settings_routes(app: "Flask", webui: "WebUI") -> None:
|
|
|
261
324
|
except Exception as e: # pylint: disable=broad-except
|
|
262
325
|
logger.exception("Error getting available sounds")
|
|
263
326
|
return jsonify({"error": str(e)}), 500
|
|
327
|
+
|
|
328
|
+
@app.route("/api/camera/url", methods=["GET"])
|
|
329
|
+
def get_camera_url():
|
|
330
|
+
"""Get the configured camera URL."""
|
|
331
|
+
try:
|
|
332
|
+
camera_url = webui.presets.camera_url
|
|
333
|
+
logger.info("Camera URL requested: '%s'", camera_url)
|
|
334
|
+
return jsonify({"camera_url": camera_url})
|
|
335
|
+
except Exception as e: # pylint: disable=broad-except
|
|
336
|
+
logger.exception("Error getting camera URL")
|
|
337
|
+
return jsonify({"error": str(e)}), 500
|
|
@@ -5,9 +5,9 @@ pumaguard/main.py,sha256=1Wazv1wjwb46yNlqgWt88HQwKSxGmY24X5OsUv8gYyE,7029
|
|
|
5
5
|
pumaguard/model-registry.yaml,sha256=V-pTaqJrk_jJo568okBDaVhs51qTHttSqKe6PqdX6Bc,10318
|
|
6
6
|
pumaguard/model_cli.py,sha256=nzDv0lXSvRKpLxs579tiHInJPPV-AFO4jzeLk5t2GaA,1394
|
|
7
7
|
pumaguard/model_downloader.py,sha256=zJQgCMOF2AfhB30VsfOMYtgRxcxVxkZBAdtG8KznPyY,12895
|
|
8
|
-
pumaguard/presets.py,sha256=
|
|
9
|
-
pumaguard/server.py,sha256=
|
|
10
|
-
pumaguard/sound.py,sha256=
|
|
8
|
+
pumaguard/presets.py,sha256=2owFBEqpeAjrFLSYtF9o3wQCc8aDjpwnU5j_YXSyIZ0,27757
|
|
9
|
+
pumaguard/server.py,sha256=zmzSXabt6K26u8kwBPdm1gI6aMAwJo3gCaSaX5Sh0vk,14705
|
|
10
|
+
pumaguard/sound.py,sha256=1qIV4NFOtyRfiIpFTnjbm_hYdNw54bGjMnopeHj_bhM,4633
|
|
11
11
|
pumaguard/stats.py,sha256=ZwocfnFCQ-ky7me-YTTrEoJqsIHOWAgSzeoJHItsIU4,927
|
|
12
12
|
pumaguard/utils.py,sha256=w1EgOLSZGyjq_b49hvVZhBESy-lVP0yRtNHe-sXBoIU,19735
|
|
13
13
|
pumaguard/verify.py,sha256=vfw3PRzDt1uuH5FKV9F5vb1PH7KQ6AEgVNhJ6jck_hQ,5513
|
|
@@ -16,20 +16,27 @@ pumaguard/completions/pumaguard-classify-completions.sh,sha256=5QySg-2Jdinj15qpU
|
|
|
16
16
|
pumaguard/completions/pumaguard-completions.sh,sha256=bRx3Q3_gM__3w0PyfQSCVdxylhhr3QlzaLCav24dfNc,1196
|
|
17
17
|
pumaguard/completions/pumaguard-server-completions.sh,sha256=33c6GjbTImBOHn0SSNUOJoxqJ2mMHuDv3P3GQJGGHhA,1161
|
|
18
18
|
pumaguard/completions/pumaguard-train-completions.sh,sha256=lI8LG-QrncvhUqCeKtfrSU1MSRBn52KnDsiJJQm37W4,1184
|
|
19
|
-
pumaguard/pumaguard-ui/.last_build_id,sha256=
|
|
19
|
+
pumaguard/pumaguard-ui/.last_build_id,sha256=44nL03JzUFDZwdvMJrofy7jk3ZWVr-aW8se0TOV0weg,32
|
|
20
20
|
pumaguard/pumaguard-ui/favicon.png,sha256=erJSX0uGtl0-THA1ihfloar29Df5nLzARtrXPVm7kBU,917
|
|
21
21
|
pumaguard/pumaguard-ui/flutter.js,sha256=7V1ZIKmGiouT15CpquQWWmKWJyjUq77FoU9gDXPFO9M,9412
|
|
22
|
-
pumaguard/pumaguard-ui/flutter_bootstrap.js,sha256=
|
|
23
|
-
pumaguard/pumaguard-ui/flutter_service_worker.js,sha256=
|
|
24
|
-
pumaguard/pumaguard-ui/index.html,sha256=
|
|
25
|
-
pumaguard/pumaguard-ui/main.dart.js,sha256=
|
|
22
|
+
pumaguard/pumaguard-ui/flutter_bootstrap.js,sha256=RYi4PhelQMs063sa3jCr0BLWDMAzY7lKs-ksCptkaQM,9692
|
|
23
|
+
pumaguard/pumaguard-ui/flutter_service_worker.js,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
pumaguard/pumaguard-ui/index.html,sha256=901-ZY0WysVAZWPwj2xGatoezwm9TX9IV_jpMrlsaXg,1205
|
|
25
|
+
pumaguard/pumaguard-ui/main.dart.js,sha256=_GkHZTEXl7rrDH_m76wch3azHo10GdLVSDxnJCJGYGM,2725345
|
|
26
26
|
pumaguard/pumaguard-ui/manifest.json,sha256=Hhnw_eLUivdrOlL7O9KGBsGXCKKt3lix17Fh3GB0g-s,920
|
|
27
27
|
pumaguard/pumaguard-ui/version.json,sha256=uXZ6musTJUZaO0N2bEbr3cy9rpx2aesAS2YFMcu2WF8,94
|
|
28
|
-
pumaguard/pumaguard-ui/assets/AssetManifest.bin,sha256=
|
|
29
|
-
pumaguard/pumaguard-ui/assets/AssetManifest.bin.json,sha256=
|
|
30
|
-
pumaguard/pumaguard-ui/assets/FontManifest.json,sha256=
|
|
31
|
-
pumaguard/pumaguard-ui/assets/NOTICES,sha256=
|
|
32
|
-
pumaguard/pumaguard-ui/assets/fonts/MaterialIcons-Regular.otf,sha256=
|
|
28
|
+
pumaguard/pumaguard-ui/assets/AssetManifest.bin,sha256=Qzp1G9iPlHSW-PnHyszTxZO31_NjmTlvSBWY_REPH_8,562
|
|
29
|
+
pumaguard/pumaguard-ui/assets/AssetManifest.bin.json,sha256=_6pfLT_4Bcd6SkcHE6GNc8Uoh6UyL4dxCaK7bypu5lc,754
|
|
30
|
+
pumaguard/pumaguard-ui/assets/FontManifest.json,sha256=TbzXC0njmfIhJ8D_sqF4P6NGmuI9BBSOl8AzaY-zNMo,598
|
|
31
|
+
pumaguard/pumaguard-ui/assets/NOTICES,sha256=pXK1o4s9viUW6snqVEqfZsFJa-43d8tCPzyBAanqn0I,1383980
|
|
32
|
+
pumaguard/pumaguard-ui/assets/fonts/MaterialIcons-Regular.otf,sha256=_jHTXqz97mq6qdprZetBY0OYMj2DjhQS8g7hSNZS9X4,11092
|
|
33
|
+
pumaguard/pumaguard-ui/assets/fonts/Roboto-Bold.ttf,sha256=YfifjbSSYcL2EG6NzMNd97L37ZCQINtAo_yQXpX5kzQ,514260
|
|
34
|
+
pumaguard/pumaguard-ui/assets/fonts/Roboto-Light.ttf,sha256=Ao-EOxmQukbiocTvG4JynE2pqUaw2djb9Z5iPRCV5FQ,518580
|
|
35
|
+
pumaguard/pumaguard-ui/assets/fonts/Roboto-Medium.ttf,sha256=KHml7Lf7-hOn_D4s3X_sv3OqRekbVB39-ixELu0KrCE,511592
|
|
36
|
+
pumaguard/pumaguard-ui/assets/fonts/Roboto-Regular.ttf,sha256=VqRSM9KfEbTfuG0kjpIZOdEVd4-HMl566MwQg4PWZk0,515100
|
|
37
|
+
pumaguard/pumaguard-ui/assets/fonts/RobotoMono-Bold.ttf,sha256=Ps815eh6zMdXi2BdH18Lww2IsZXWgHvsigxX9qqVxNs,126680
|
|
38
|
+
pumaguard/pumaguard-ui/assets/fonts/RobotoMono-Medium.ttf,sha256=SsuyclomDq__G8qt41ASBMp3TlY0biWe4bYdVpltJhE,127268
|
|
39
|
+
pumaguard/pumaguard-ui/assets/fonts/RobotoMono-Regular.ttf,sha256=rwv_dZnD3zgxdVwW45s8SW33S4yNihFhsU3IRhvhfLQ,125748
|
|
33
40
|
pumaguard/pumaguard-ui/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf,sha256=PZDDcKpM8A3FfuK5AvZlIUfA-B4D5IPfWEqcCLFofJ0,1472
|
|
34
41
|
pumaguard/pumaguard-ui/assets/shaders/ink_sparkle.frag,sha256=4Bths5TPZqZBvqh-O0_jeH03L2Nsi8iipnQ4zcKdpvY,8867
|
|
35
42
|
pumaguard/pumaguard-ui/assets/shaders/stretch_effect.frag,sha256=-pzPjkKWMaRhx6fGRNq6gRpTRj94qirQI-DpyBuBW0o,6714
|
|
@@ -55,9 +62,9 @@ pumaguard/web_routes/diagnostics.py,sha256=EIIbjuixJyGXdnVQf8RQ6xQxJar0UHZO8dF-9
|
|
|
55
62
|
pumaguard/web_routes/directories.py,sha256=yy5TghCEyB4reRGAcVHIEfr2vlHnuiDChIXl9ZFquRM,2410
|
|
56
63
|
pumaguard/web_routes/folders.py,sha256=Z63ap6dRi6NWye70HYurpCnsSXmFgzTbTsFKYdZ1Bjk,6305
|
|
57
64
|
pumaguard/web_routes/photos.py,sha256=Tac_CbaZSeZzOfaJ73vlp3iyZbvfD7ei1YM3tsb0nTY,5106
|
|
58
|
-
pumaguard/web_routes/settings.py,sha256=
|
|
65
|
+
pumaguard/web_routes/settings.py,sha256=kjSqoX6E38UJ_J_YZRQr7QmACR7bDwFcUarqnowjHP4,11655
|
|
59
66
|
pumaguard/web_routes/sync.py,sha256=Zvv6VARGE5xP29C5gWH3ul81PISRxoF8n472DITItE0,6378
|
|
60
|
-
pumaguard-20.
|
|
67
|
+
pumaguard-20.post240.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
61
68
|
pumaguard-sounds/cougar_call.mp3,sha256=jdPzi7Qneect3ez2G6XAeHWtetU5vSOSB6pceuB26Wc,129048
|
|
62
69
|
pumaguard-sounds/cougarsounds.wav,sha256=hwVmmQ75dkOP3qd07YAvVOSm1neYtxLSzxw3Ulvs2cM,96346
|
|
63
70
|
pumaguard-sounds/dark-engine-logo-141942.mp3,sha256=Vw-qyLTMPJZvsgQcZtH0DpGcP1dd7nJq-9BnHuNPGug,372819
|
|
@@ -75,8 +82,8 @@ pumaguard-sounds/mixkit-vintage-telephone-ringtone-1356.wav,sha256=zWWY2uFF0-l7P
|
|
|
75
82
|
pumaguard-sounds/pumaguard-warning.mp3,sha256=wcCfHsulPo5P5s8MjpQAG2NYHQDsRpjqoMig1-o_MDI,232249
|
|
76
83
|
pumaguard-sounds/short-round-110940.mp3,sha256=vdskGD94SeH1UJyJyR0Ek_7xGXPIZfnPdoBvxGnUt98,450816
|
|
77
84
|
pumaguard-ui/ios/Flutter/ephemeral/flutter_lldb_helper.py,sha256=Bc_jl3_e5ZPvrSBJpPYtN05VxpztyKq-7lVms3rLg4Q,1276
|
|
78
|
-
pumaguard-20.
|
|
79
|
-
pumaguard-20.
|
|
80
|
-
pumaguard-20.
|
|
81
|
-
pumaguard-20.
|
|
82
|
-
pumaguard-20.
|
|
85
|
+
pumaguard-20.post240.dist-info/METADATA,sha256=uE_jBxjvZQ7SMR0DF4LEAElU9NdCUhH9QdElUYqWGvk,8618
|
|
86
|
+
pumaguard-20.post240.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
87
|
+
pumaguard-20.post240.dist-info/entry_points.txt,sha256=rmCdBTPWrbJQvPPwABSVobXE9D7hrKsITGZ6nvCrko8,127
|
|
88
|
+
pumaguard-20.post240.dist-info/top_level.txt,sha256=B-PzS4agkQNhOYbLLIrMVOyMD_pl5F-yujPBm5zYYjY,40
|
|
89
|
+
pumaguard-20.post240.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|