-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
166 lines (134 loc) · 5.05 KB
/
app.py
File metadata and controls
166 lines (134 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import eel
import os
import sys
import logging
import threading
from ltc_generator import FrameRate, LTCConfig, LTCGenerator
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
_generation_lock = threading.Lock()
@eel.expose
def get_frame_rates() -> list:
"""Get all available frame rates for the UI"""
return FrameRate.get_all_frame_rates()
@eel.expose
def get_sample_rates() -> list:
"""Get all available sample rates for the UI"""
return [44100, 48000, 96000, 192000]
@eel.expose
def get_bit_depths() -> list:
"""Get all available bit depths for the UI"""
return [16, 24]
@eel.expose
def generate_ltc(frame_rate_name: str, sample_rate: int, bit_depth: int,
hours: int, minutes: int, seconds: int, frames: int,
duration: float, output_path: str) -> dict:
"""Generate LTC timecode file"""
logger.info("LTC generation requested: frame_rate=%s, sample_rate=%s, "
"bit_depth=%s, start=%02d:%02d:%02d:%02d, duration=%s, output=%s",
frame_rate_name, sample_rate, bit_depth,
int(hours), int(minutes), int(seconds), int(frames),
duration, output_path)
if not _generation_lock.acquire(blocking=False):
logger.warning("Generation rejected: another generation is already in progress")
return {
"success": False,
"message": "Another generation is already in progress. Please wait."
}
try:
# Convert parameters to appropriate types
sample_rate = int(sample_rate)
bit_depth = int(bit_depth)
hours = int(hours)
minutes = int(minutes)
seconds = int(seconds)
frames = int(frames)
duration = float(duration)
# Validate inputs
if duration <= 0:
raise ValueError("Duration must be greater than 0")
if duration > 7200: # 2 hours in seconds
raise ValueError("Duration cannot exceed 2 hours")
# Validate output path is within user home directory
resolved = os.path.abspath(output_path)
home = os.path.expanduser("~")
if not resolved.startswith(home):
raise ValueError("Output path must be within user home directory")
# Get frame rate enum from name
frame_rate = FrameRate.get_frame_rate_by_name(frame_rate_name)
# Validate frame number against frame rate
max_frames = round(frame_rate.get_fps())
if frames >= max_frames:
raise ValueError(f"Frame number must be less than {max_frames} for {frame_rate.get_display_name()}")
# Create configuration
config = LTCConfig(
frame_rate=frame_rate,
sample_rate=sample_rate,
bit_depth=bit_depth,
start_time=(hours, minutes, seconds, frames),
duration_seconds=duration
)
# Create generator
generator = LTCGenerator(config)
# Make sure output directory exists
os.makedirs(os.path.dirname(resolved), exist_ok=True)
# Generate LTC file
try:
generator.export_wav(output_path)
except Exception:
# Clean up partial file on failure
if os.path.exists(output_path):
os.remove(output_path)
raise
logger.info("LTC generation successful: %s", output_path)
# Return success
return {
"success": True,
"message": f"Generated LTC timecode file: {output_path}",
"file_path": output_path
}
except (ValueError, IOError, OSError) as e:
logger.error("LTC generation failed: %s", e)
# Return error
return {
"success": False,
"message": f"Error generating LTC: {str(e)}"
}
finally:
_generation_lock.release()
@eel.expose
def browse_save_path() -> str:
"""Open a file dialog for choosing where to save the LTC file"""
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.withdraw()
root.attributes('-topmost', True)
path = filedialog.asksaveasfilename(
defaultextension=".wav",
filetypes=[("WAV files", "*.wav")],
title="Save LTC File"
)
root.destroy()
return path or ""
@eel.expose
def get_default_output_path() -> str:
"""Get default output path based on user's desktop"""
desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
return os.path.join(desktop_path, "ltc_timecode.wav")
def main() -> None:
"""Main application entry point"""
try:
# Set configuration options
eel.init('web')
# Start Eel with Chrome (or default browser if Chrome not found)
eel.start('index.html', size=(1000, 700))
except EnvironmentError:
# If Chrome isn't found, fallback to Microsoft Edge on Windows
if sys.platform in ['win32', 'win64']:
eel.start('index.html', mode='edge')
else:
# Fallback to the default browser
eel.start('index.html', mode='default')
if __name__ == "__main__":
main()