-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathStopWatch-[4.10].lua
7005 lines (5995 loc) · 264 KB
/
StopWatch-[4.10].lua
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Open Broadcaster Software®️
OBS > Tools > Scripts
@midnight-studios
Stopwatch
***************************************************************************************************************************************
Version 4.10
Published / Released: 2023-02-09 10:00
NEW FEATURES
-
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
- Fixed an issue 'Reset Timer on Source Visible'.
- Fixed an issue 'Reset Timer on Scene Active'.
***************************************************************************************************************************************
Version 4.9
Published / Released: 2023-02-09 10:00
NEW FEATURES
-
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
- Fixed an issue that caused the time marker function to break.
***************************************************************************************************************************************
Version 4.8
Published / Released: 2023-02-02 10:45
NEW FEATURES
- Custom Minute Format that supports minute formats of any length. To use open Scipt settings go to 'Time Format' and set to 'Custom Time Format' and define the time stamp you require. To adjust the minute format you need to add the following syntax: '{M90}' Add 'M' and number enclosed in '{}' to adjust minute format: {M90} will display 90 minutes units. The number value following the 'M' will be assigned to the Minute Format
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
-
***************************************************************************************************************************************
***************************************************************************************************************************************
Version 4.7
Published / Released: 2022-12.29 18:56
NEW FEATURES
- Expanded Add / Subtract seconds to time.
- Alow this feature to be hidden or disabled
- This feature now allows a limit for updating the timer (Zero = infinite)
- A source text note can be defined to notify the user when the limit was reached
- User can define how long the note is displayed (Zero = disables the hide feature)
OPTIMIZATION
- some back end improvements or changes
USER EXPERIENCE & FEATURE ENHANCEMENTS
- Some improvements with conflict prevention for text source selection
- Renamed 'Autoload last time stamp on OBS start'
BUGS
- Fixed some bugs introduced during the previous release
- Fixed an issue that caused timer to crash when OBS shuts down if the script was duplicated (used multiple times) [@Xagika]
- Fixed a bug that would reset the timer if user enables 'auto load end timsestamp'
***************************************************************************************************************************************
Version 4.6
Published / Released: 2022-12.20 12:48
NEW FEATURES
- Allow Timer reset if scene becomes activated
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
- Start on Scene active improvements
BUGS
- Fixed an issue that caused the stinger transition to break when the timer is in countdown mode.
***************************************************************************************************************************************
Version 4.5
Published / Released: 2022-12.03 01:56
NEW FEATURES
- Add / Subtract seconds to time (3 sets available, configurable up to 72 hours or 259200 seconds)
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
-
***************************************************************************************************************************************
Version 4.4
Published / Released: 2022-11.04 19:25
NEW FEATURES
- Change counter direction
- Prevent Negative Time Value (Opt-In)
- Enable / Disable new feature: Change counter direction (Opt-In)
- Hotkey and Button to change counter direction (Supported in Stopwatch and Countdown mode)
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
-
***************************************************************************************************************************************
Version 4.3
Published / Released: 2022-10.20 11:51
NEW FEATURES
-
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
- Fixed the expired timestamp for 'custom time format'
***************************************************************************************************************************************
Version 4.2
Published / Released: 2022-10.20 21:23
NEW FEATURES
- Add Media Playback for Timer end
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
- Changed Property Setting label 'Trigger Text' to 'Marker Notes'
BUGS
- Fixed an infinate timer callback loop
- Reverted and applied new Fix for timer Reset issue
- Fixed an issue for recording call when recording is already active
- Fixed switching "split type" does not reset the timer display
- Fixed changing "Mark Time" does not reset the timer display
- Fixed timer display color reset after Mark A & B conditions were met
- Fixed stopping Media playback if media is set to loop when the timer expires
- Fixed a routine issue on sources loaded
- Fixed a timer reset issue (for activate timer on visible)
- Fixed a load 'last saved time' issue (for activate timer on visible)
- Fixed a 'set stopwatch' issue (for activate timer on visible)
***************************************************************************************************************************************
Version 4.1
Published / Released: 2022-10.06 15:23
NEW FEATURES
-
OPTIMIZATION
-
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
- Fixed timer Reset issue
***************************************************************************************************************************************
Version 4.0
Published / Released: 2022-10.06 12:26
NEW FEATURES
-
OPTIMIZATION
- Backend updates
USER EXPERIENCE & FEATURE ENHANCEMENTS
-
BUGS
- Fixed a signal handler crash due to an unloaded source
- Fixed a bug that triggered the Media when the timer was not active
***************************************************************************************************************************************
Version 3.9
Published / Released: 2022-10.10 15:15
NEW FEATURES
- Added button Show / Hide Milliseconds
- Added Time Stamp trigger for Show / Hide Milliseconds
- Added Timer text output options (Still not convinvinced this makes sense)
- Added Hotkey for Show / Hide Milliseconds
- Pause Media if timer is paused
- Added option to force visibility of the "Active Source"
OPTIMIZATION
- OBS 28 Supported
- Rebuild timer text options
- Prevented unnecessary Callback Events
- Localized functions to reduce Globals clutter
- Renamed some functions to something more sensible
- Added and updated developer code comments
- Realigned function stacking order
- Renamed Hotkey references
USER EXPERIENCE & FEATURE ENHANCEMENTS
- Added tooltip for Next Scene list
- Added tooltip for Recording list
- Items listed in Cycle Sources list will ignore incorrectly referenced sources.
- User can now define the direction of Cycle Sources
- Cycle Sources (and toggle source visibility) with timer is now fully automated without third party plugins/scripts
- Cycle Sources now support Nested Scenes
- Added new Toggles for settings properties to hide or show certain settings
BUGS
- Fixed a Stack Overflow Crash produced by the Next Scene process.
- Fixed an issue that caused a timer feature to break.
- Fixed a critical memory leak for media sources that caused OBS to crash
- Fixed Media Playback time limit
- Fixed Split time outputs for Stopwatch
----------------------------------------------------------------------------------------------------------------------------------------
]]
--Globals
obs = obslua;
gversion = "4.10";
luafile = "StopWatch.lua";
obsurl = "comprehensive-stopwatch-countdown-timer.1364/";
patch_notes = "Patch Notes";
icon="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAYAAACpF6WWAAAENElEQVQ4jY1UTUgjZxh+ksl/JuMkMYb4F40bNZqK0KJFqBZqS9ddyl76dyhdKPRQShH2sNDSnnopCz11D10KS/dSKNiDoD2I7KXFQ0XSSGpM1llFMYn5mZiMY2IymfIOhgazXfaDj5n53u975vme531fnaqqeMHxJYCvAOgAlABcAyA1jxLO1tYW1tbWoL+Kd3x8jGg0imw2C0VRWkMEYgNgBeAFYKTFRqOh7aVnE9xwFTSZTGJ7exszMzPQ6XSQZRk8z9P7YrVa/Y5hmKLBYHCpqirW63Wcn5/j7OwMHo9HA6bvNqY2mw1Op1N70qaTkxPkcjmbLMsDZrN5hOO4NxuNhlMUxTFiSCA0FEW5GQ6H/wmHwzfamDavUKlUYDKZAoFA4Gue52/r9f/9v6OjQ5uKojwpFAr3RFF8UCwWjW63OzQ/P/9yGyiBnZ6eEtN3eZ7/9XJZrlQqP2cymcf5fL4QDAbHdTrd2yzLXvd4PD9yHHdLEISFXC7nsdvtuTb3c7kcEokEJiYmhliWtaiqWs5ms4f1el0lE2lOTU0hn8/DYrF09vb23jebze9JkvRXNBqdMpvNaIJaLh1tHScAzpvsSd+joyOkUimEQiFNa4vFAlEU4Xa7HwYCgduFQuHRxsbGx5p+qqq+o/7/SF7uQSaTwcHBgZYdgiBMqKqa2dnZ8S8tLaFcLicIIR6PjzU13Qew+gzPKNEj9JJOp5tag+O41/v7+x/v7u7+sLOzc8BxHN1icXR0dMXlcn3xQhW1v7+PSCSC6enptxwOx3WWZRcbjcbTjY2NAJ1nWRYGgwHj4+OqoigFYnr/UlPlClYFwJ1arVYjU8bGxhZ8Pt9KMxiLxd5gGEbTlTSv1WqQJOmJw+G4RqCfPYfkN4qiFDs7O9HT0/Nqa4BhmKd2u10DrFaruLi4oJmncibQSUCrLHJabDlHzItGo1E7FIvFvg+FQjMmkykkCMK9eDwOivl8PvqhBspxXJAOEujfz2HazzBMdXh4OJNMJoupVGre7/cbBEGor6+vY2RkROsLlwY6jUajS5KkSGvtf0oVemUeAPiDgsFgUHMeQJ3MmZycxNzcnMZWkiT4/f67FJRl+UFrmcYB/N7y3UyLSHOBzNjb20MgEMDg4CC6urqwublJZo12d3ffVRRFEQTh4TNTqlQqaawoTShOVdOsqMPDQ8zOzmqFQK3PZrO91NPTs2U0GkmWG4lEYrWt9cViMSwvL1Ntvw9gRafT/aTX6z8AwFKcuhU5zjDMkNfr/XZgYCBKgMfHx3eSyeSqw+Fob9LEipxMp9MRp9P5uclkWuB5/hOKWa3Wvb6+vjLP8wNer5fXUkRRLkql0ofZbPY3ug019TZQ6jKU0AzD7Iqi+Josy6+4XK6P7Hb7LbvdPkS5SXpXKpU/ZVn+5ezs7FG9Xi9brVZNLr1ej38BVDs6EbSfFQsAAAAASUVORK5CYII=";
desc =
[[
<hr/><center><h2>Advanced Stopwatch</h2>( Version: %s )</center>
<br><center><img width=38 height=42 src="]] .. icon .. [["/></center>
<br><center><a href="https://github.com/midnight-studios/obs-lua/blob/main/]] .. luafile ..[[">Find it on GitHub</a></center>
<center><a href="https://obsproject.com/forum/resources/]] .. obsurl ..[[updates">]] .. patch_notes ..[[</a></center>
<br><p>The Properties for this script will adjust visibility as needed. Some advanced properties will only be visible if the Configuration is set to "Advanced". If the Configuration is set to "Basic" the defined values will still be used, so ensure you define those correctly.</p><p>Find help on the <a href="https://obsproject.com/forum/resources/]] .. obsurl ..[[">OBS Forum Thread</a>.</p><hr/>
]];
text_prefix = "";
text_suffix = "";
last_text = "";
custom_time_format = "";
timer_source = "";
countdown_type = "";
backup_folder = "";
import_list = "";
longtimetext_s = "";
longtimetext_p = "";
last_split_data = "";
split_source = "";
active_source = "";
next_scene = "";
stop_text = "";
toggle_mili_trigger = "";
sec_add_1 = "";
sec_add_2 = "";
sec_add_3 = "";
sec_sub_1 = "";
sec_sub_2 = "";
sec_sub_3 = "";
output_file_name = "-backup($date_stamp).json";
font_normal = "#ffffff";
font_dimmed = "#bfbbbf";
font_highlight = "#fffdcf";
add_limit_note_source = "";
sub_limit_note_source = "";
note_source_marker_a = "";
note_source_marker_b = "";
add_limit_note_source_visible = 0;
sub_limit_note_source_visible = 0;
sources_loaded = 0;
timer_manipulation = 1;
sec_add_limit = 0;
sec_add_limit_used = 0;
sec_sub_limit_used = 0;
sec_sub_limit = 0;
total_sources = 0;
sw_hours_saved = 0;
sw_minutes_saved = 0;
sw_seconds_saved = 0;
sw_milliseconds_saved = 0;
split_type = 2;
current_seconds = 0;
cycle_direction = 1;
default_seconds = 0;
split_count = 0;
timer_year = 0;
timer_month = 0;
timer_day = 0;
timer_hours = 0;
timer_minutes = 0;
timer_seconds = 0;
timer_mode = 0;
last_timer_mode = 0;
timer_format = 1;
timer_display = 1;
start_recording = 0;
media_playback_limit = 0;
recording_type = 0;
enable_marker_notes = 1;
orig_time = 0;
time_frequency = 0;
completed_cycles = 0;
ns_last = 0;
cycle_index = 1;
current_count_direction = 1;
timer_cycle = 10; --milliseconds
split_itm = {};
split_data = nil;
minute_format = nil;
local ctx = {
propsDef = nil, -- property definition
propsDefSrc = nil, -- property definition (source scene)
propsSet = nil, -- property settings (model)
propsVal = {}, -- property values
propsValSrc = nil, -- property values (first source scene)
};
props = nil;
timer_mode_changed = false;
set_timer_activated = false;
color_normal_updated = false;
activated = false;
prevent_callback = false;
timer_active = false;
reset_activated = false;
start_on_visible = false;
force_reset_on_visible = false;
force_reset_on_scene_active = false;
active_source_force_visible = false;
start_on_scene_active = false;
disable_script = false;
enable_direction_toggle = false;
show_mili = true;
timer_expired = true;
mili_toggle_triggered = false;
direction_changed = false;
prevent_negative_time = false;
record_timer_set = false;
media = { -- table start
text_marker_b = "",
text_marker_a = "",
source_name_audio_marker_b = "",
source_name_audio_marker_a = "",
source_name_audio_marker_end = "",
note_source_marker_a = "",
note_source_marker_b = "",
note_marker_a = "",
note_marker_b = "",
activated_marker_b = false,
activated_marker_a = false,
current_seconds_marker_a = 0,
current_seconds_marker_b = 0,
duration_marker_a = 0,
duration_marker_b = 0,
duration_marker_end = 0,
media_ended_marker_a = false,
media_ended_marker_b = false,
color_normal = 4294967295, -- 4294967295 0xFFFFFFFF
color_marker_a = 4256749, -- 4256749 0x40f3ed
color_marker_b = 329050, -- 329050 0x05055a
last_state_marker_a = obs.OBS_MEDIA_STATE_NONE,
last_state_marker_b = obs.OBS_MEDIA_STATE_NONE
}; -- table end
selected_source_list = {};
hotkey_id_reset = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_pause = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_split = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_mili = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_direction = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_sec_add_1 = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_sec_add_2 = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_sec_add_3 = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_sec_sub_1 = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_sec_sub_2 = obs.OBS_INVALID_HOTKEY_ID;
hotkey_id_sec_sub_3 = obs.OBS_INVALID_HOTKEY_ID;
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: A function named script_description returns the description shown to
the user
Credit: OBS
Modified: User dependent
function: Script Description
type: OBS Core
input type: data
returns: string
----------------------------------------------------------------------------------------------------------------------------------------
]]
function script_description()
return string.format( desc, tostring( gversion ) );
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Dumps input to string, if input is a table it returns the expanded table
Credit: et al
Modified: yes
function:
type: Support (debug tool)
input type: variable
returns: string
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function pre_dump( input )
if type( input ) == "table" then
local str = "{ ";
for key, value in pairs( input ) do
if type( key ) ~= "number" then key = "'" .. key .. "'" end;
str = str .. "[" .. key .. "] = " .. pre_dump( value ) .. ",";
end;
return str .. "} ";
else
return tostring( input );
end;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Use this to create a Script Log Output used in testing
Credit: et al
Modified: No
function:
type: Support (debug tool)
input type: string
returns: print(string)
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function log( name, msg )
if msg ~= nil then
msg = " > " .. tostring( msg );
else
msg = "";
end;
obs.script_log( obs.LOG_DEBUG, tostring( name ) .. msg );
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Builds a table by splitting a string by defined character or sequence of characters marking
the beginning or end of a unit of data. That which delimits, that separates.
Credit: midnight-studios, et al
Modified:
function: breaks string into sections by a reference that is returned in a table
type:
input type: string, delimiter
returns: table
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function explode( str, delim )
local tbl, index;
tbl = {};
index = 0;
if( #str == 1 ) then return {str} end; -- returns a table with the input string as the only value
while true do
local trace_index = string.find( str, delim, index, true ); -- find the next d in the string
if trace_index ~= nil then -- if "not not" found then..
table.insert( tbl, string.sub( str, index, trace_index - 1 ) ); -- Save it in our array.
index = trace_index + 1; -- save just after where we found it for searching next time.
else
table.insert( tbl, string.sub( str, index ) ); -- Save what's left in our array.
break; -- Break at end, as it should be, according to the lua manual.
end;
end;
return tbl;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Gives you an iterator that moves through an
ordinary table (eg. string keys) but sorted
into key sequence.
It does that by copying the table keys into
a temporary table and sorting that.
Possibly being string referenced the list
will be compiled chronologically, thus the
list names (values) may appear unordered and
random. To reorganise and arrange the list
alphabetically we will use pairsByKeys().
This will make it easier for the user to review
and select the desired item from the list.
Credit: https://github.com/nickgammon/mushclient/blob/master/lua/pairsbykeys.lua
https://github.com/nickgammon/mushclient/tree/master/lua
If you need to sort keys other than strings, see:
See: http://lua-users.org/wiki/SortedIteration
Modified: Yes, minor changes
function: support: This prints the math functions in key order
type: sort table
input type: table, function (optional)
returns: table
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function pairsByKeys( tbl, input_function )
if type( tbl ) ~= "table" then return tbl end; -- if the input table is not of type table return input
local temp_tbl = {}; -- build temporary table of the keys
for items in pairs( tbl ) do table.insert( temp_tbl, items ) end;
table.sort( temp_tbl, input_function ); -- sort using supplied function, if any
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1;
if temp_tbl[i] == nil then return nil;
else return temp_tbl[i], tbl[temp_tbl[i]];
end;
end;
return iter;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Provides the length of a table
(how many items the table contains)
Credit: midnight-studios, et al
Modified: Author
function: Create a table with unique items
type: Support
input type: table
returns: integer
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function tablelength( tbl )
local count = 0;
if type( tbl ) == "table" then -- if the input table is not of type table return 0
for _ in pairs( tbl ) do count = count + 1 end;
end;
return count;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Remove duplicated values from table
Credit: midnight-studios, et al
Modified: Author
function: Create a table with unique items
type: Support
input type: table, string
returns: bool
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function tableHasKey( tbl, key )
if type( tbl ) ~= "table" then return false end; -- if the input table is not of type table return bool(false)
return tbl[key] ~= nil;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Remove duplicated values from table
Credit: midnight-studios, et al
Modified: Author
function: Create a table with unique items
type: Support
input type: table, string
returns: bool
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function in_table( tbl, input_value )
if type( tbl ) ~= "table" then return false end; -- if the input table is not of type table return bool(false)
local found = false; -- set result default bool (not found)
for key, value in pairs( tbl ) do
if value == input_value then -- compare search value against table value
found = true; -- found, update result bool
break; -- found, end and exit here
end;
end;
return found; -- return bool
end
--[[
----------------------------------------------------------
Description:
Credit:
Modified:
function:
type:
input type:
returns:
----------------------------------------------------------
]]
function refresh_properties()
return true;
end
--[[
----------------------------------------------------------
Description: Remove duplicated values from table
Credit: midnight-studios, et al
Modified: Author
function: Create a table with unique items
type: Support
input type: table
returns: table
----------------------------------------------------------
]]
local function remove_duplicates( tbl )
if type( tbl ) ~= "table" then return table end; -- if the input table is not of type table return input
local hash = {};
local clean_tbl = {};
for _, value in pairsByKeys( tbl ) do
if ( not hash[value] ) then
clean_tbl[#clean_tbl+1] = value; -- you could print here instead of saving to result table if you wanted
hash[value] = true;
end;
end;
return clean_tbl; -- return final result
end
--[[
----------------------------------------------------------
Description: This is basically obs.obs_enum_sources()
but "Nested Scenes" are not listed in "obs.obs_enum_sources()"
Credit: midnight-studios, et al
Modified: Author
function: Used to build a list from OBS source names into a table
type: Support
input type: "id", "unversioned_id", "display_name", "source_name"
returns: table default with "source_name" or define return_ref: "id" or "unversioned_id" or "display_name" or "source_name"
----------------------------------------------------------
]]
function get_source_list( return_ref )
local scenes = obs.obs_frontend_get_scenes();
local source_list = {};
local list = {};
local sub = {};
--[[
]]
if scenes ~= nil then
--[[
]]
for key_scenesource, value_scenesource in pairs( scenes ) do
local scenename = obs.obs_source_get_name( value_scenesource );
local scene = obs.obs_scene_from_source( value_scenesource );
local sceneitems = obs.obs_scene_enum_items( scene );
--[[
]]
local index = 0;
for key_sceneitem, value_sceneitem in pairs( sceneitems ) do
index = index + 1;
sub = {};
local source = obs.obs_sceneitem_get_source( value_sceneitem );
local source_name_parent = obs.obs_source_get_name( source );
local group = obs.obs_group_from_source( source );
local id_parent = obs.obs_source_get_id( source );
local unversioned_id_parent = obs.obs_source_get_unversioned_id( source );
local display_name_parent = obs.obs_source_get_display_name( id_parent );
sub["id"] = id_parent;
sub["unversioned_id"] = unversioned_id_parent;
sub["display_name"] = display_name_parent;
sub["source_name"] = source_name_parent;
list[index] = sub;
source_list[source_name_parent] = source_name_parent; -- will return this by default if return_ref not defined as the name is a unique id
if group ~= nil then
local groupitems = obs.obs_scene_enum_items( group );
if groupitems ~= nil then
for key_groupitem, value_groupitem in pairs( groupitems ) do
index = index + 1;
sub = {};
local groupitemsource = obs.obs_sceneitem_get_source( value_groupitem );
local source_name_group = obs.obs_source_get_name( groupitemsource );
local id_group = obs.obs_source_get_id( groupitemsource );
local unversioned_id_group = obs.obs_source_get_unversioned_id( groupitemsource );
local display_name_group = obs.obs_source_get_display_name( id_group );
sub["id"] = id_group;
sub["unversioned_id"] = unversioned_id_group;
sub["display_name"] = display_name_group;
sub["source_name"] = source_name_group;
list[index] = sub;
source_list[source_name_group] = source_name_group; -- will return this by default if return_ref not defined as the name is a unique id
end -- end for
obs.sceneitem_list_release( groupitems );
end
end
end -- end for in pairs( sceneitems )
obs.sceneitem_list_release( sceneitems );
end -- end for in pairs( scenes )
--[[
]]
obs.source_list_release( scenes );
end; -- scenes ~= nil
--[[
is "return_ref" defined and a valid (existing) reference?
]]
local tmp_list = {};
local found = false;
if return_ref ~= nil then
for key, value in pairs( list ) do
if type( list[key] ) == "table" then
if tableHasKey( list[key], return_ref ) then
found = true;
tmp_list[list[key]["source_name"]] = list[key][return_ref];
end;
end;
end;
end;
if found then source_list = tmp_list end;
return source_list;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Function to convert OBS data array to table
obs_data_array_to_table( settings, "reference" )
Description: Grab OBS data array and return in a table
Credit: midnight-studios
Modified:
function: data array to table
type: Support
input type: Settings, property reference
returns: table
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function obs_data_array_to_table( set, item )
local array = obs.obs_data_get_array( set, item );
local count = obs.obs_data_array_count( array );
local list = {};
for i = 0, count do
local array_item = obs.obs_data_array_item( array, i );
local value = obs.obs_data_get_string( array_item, "value" );
list[i] = value;
end;
obs.obs_data_array_release( array );
return list;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Get the name of this script
Credit: midnight-studios, et al
Modified:
function: regular expression
type: Support
input type: string
returns: string
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function filename()
local str = debug.getinfo(2).source:sub(2);
return str:match("^.*/(.*).lua$") or str;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: List files
Credit: midnight-studios
Modified: midnight-studios, et al
function: Used to list files with target extension
type: directory path, file extension
input type:
returns: table
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function get_filenames( path, file_extension )
local filenames = {};
local dir = obs.os_opendir( path );
local entry;
repeat
entry = obs.os_readdir( dir );
if entry then
local ext = obs.os_get_path_extension( entry.d_name );
if ext == file_extension then
local filename = string.gsub( entry.d_name, ext, "" );
table.insert( filenames, filename );
end
end
until not entry;
obs.os_closedir( dir );
return filenames;
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Convert data to json
Credit: midnight-studios, et al
Modified: Yes, custom params to suit targeted need
function:
type: Support
input type: OBS data (Settings)
returns: json file
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function write_to_json( data )
output_folder = backup_folder;
-- convert Windows path to UNIX path
local file_name = filename() .. output_file_name:gsub("$date_stamp", os.date("%Y-%m-%d-%H%M"));
-- set output path as the script path by default
local script_path = script_path();
local output_path = script_path .. file_name;
-- if specified output path exists, then set this as the new output path
if (output_folder ~= "") then
output_path = output_folder .. "/" .. file_name;
else
output_path = script_path .. file_name;
end
output_path = output_path:gsub([[\]], "/");
obs.obs_data_erase( data, "backup_folder" );
obs.obs_data_erase( data, "backup_mode" );
return obs.obs_data_save_json( data, output_path );
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description: Assign a default Frequency based on the Frame Rate
video_info.base_width
video_info.base_height
video_info.fps_den
video_info.output_width
video_info.output_height
video_info.range
video_info.colorspace
Credit: midnight-studios
Modified:
function: Get obs user defined video frame rate
type: Support
input type: none
returns: double
----------------------------------------------------------------------------------------------------------------------------------------
]]
local function assign_default_frequency()
local fps = 60; -- 60 is the maximum supported frame rate
local video_info = obs.obs_video_info();
if obs.obs_get_video_info(video_info) then
fps = video_info.fps_num;
end;
time_frequency = ( 1/fps );
end
--[[
----------------------------------------------------------------------------------------------------------------------------------------
Description:
Local variables format_hour, format_minutes, format_seconds, format_mili are initialized to the strings that define the format of hour, minutes, seconds and mili based on whether they are present or not.
"time" variable is initialized with the formatted string using string.format and the values of format_hour, format_minutes, format_seconds, format_mili and the input arguments hour, minutes, seconds, and mili.
If show_mili is false, then time is re-initialized with the formatted string using string.format and values of format_hour, format_minutes, format_seconds and input arguments hour, minutes, and seconds.
Return time.
Take the time segments:
Hours, Minutes, Seconds, Millisieconds
Configure to standard format:
HH:MM:SS:FF
$function status: in service
Credit: midnight-studios
Modified: