0 |
--[[ |
1 |
Subtitles — adds subtitles to Minetest. |
2 |
|
3 |
Copyright © 2022‒2023, Silver Sandstone <@SilverSandstone@craftodon.social> |
4 |
|
5 |
Permission is hereby granted, free of charge, to any person obtaining a |
6 |
copy of this software and associated documentation files (the "Software"), |
7 |
to deal in the Software without restriction, including without limitation |
8 |
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 |
and/or sell copies of the Software, and to permit persons to whom the |
10 |
Software is furnished to do so, subject to the following conditions: |
11 |
|
12 |
The above copyright notice and this permission notice shall be included |
13 |
in all copies or substantial portions of the Software. |
14 |
|
15 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 |
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
20 |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
21 |
DEALINGS IN THE SOFTWARE. |
22 |
]] |
23 |
|
24 |
|
25 |
--- Public API functions. |
26 |
|
27 |
|
28 |
local S = subtitles.S; |
29 |
|
30 |
|
31 |
subtitles.registered_descriptions = {}; |
32 |
subtitles.registered_parameters = {}; |
33 |
subtitles.agents_by_player = {}; |
34 |
subtitles.reported_missing = {}; |
35 |
|
36 |
|
37 |
--- Handles a call to minetest.sound_play(), or an equivalent event. |
38 |
-- @param spec A SimpleSoundSpec. |
39 |
-- @param parameters The sound parameters. |
40 |
-- @param handle The sound's handle, or nil if the sound is ephemeral. |
41 |
function subtitles.on_sound_play(spec, parameters, handle) |
42 |
local sound = subtitles.Sound(spec, parameters, handle); |
43 |
if sound:is_exempt() then |
44 |
return; |
45 |
end; |
46 |
for __, player in ipairs(sound:get_players()) do |
47 |
local agent = subtitles.get_agent(player); |
48 |
if agent:get_enabled() and sound:is_in_range_of_player(player) then |
49 |
local display = agent:get_display(); |
50 |
display:handle_sound_play(sound); |
51 |
end; |
52 |
end; |
53 |
end; |
54 |
|
55 |
|
56 |
--- Handles a call to minetest.sound_stop(), or an equivalent event. |
57 |
-- @param handle The sound's handle. |
58 |
function subtitles.on_sound_stop(handle) |
59 |
for username, agent in pairs(subtitles.agents_by_player) do |
60 |
agent:get_display():handle_sound_stop(handle); |
61 |
end; |
62 |
end; |
63 |
|
64 |
|
65 |
--- Returns the Agent object associated with the specified player. |
66 |
-- The agent is created if necessary. |
67 |
-- @param player A username or `ObjectRef` of a connected player. |
68 |
-- @return An `Agent` object. |
69 |
function subtitles.get_agent(player) |
70 |
if minetest.is_player(player) then |
71 |
player = player:get_player_name(); |
72 |
end; |
73 |
|
74 |
local agent = subtitles.agents_by_player[player]; |
75 |
if not agent then |
76 |
agent = subtitles.Agent(player); |
77 |
subtitles.agents_by_player[player] = agent; |
78 |
end; |
79 |
return agent; |
80 |
end; |
81 |
|
82 |
|
83 |
--- Handles a node action. |
84 |
-- @param pos The position of the node, as a integer vector. |
85 |
-- @param node The node table or node name. |
86 |
-- @param action A key in the `sounds` table, such as 'dig' or 'footstep'. |
87 |
function subtitles.on_node_action(pos, node, action) |
88 |
if type(node) ~= 'string' then |
89 |
node = node.name; |
90 |
end; |
91 |
|
92 |
local spec = subtitles.util.get_node_sound(node, action); |
93 |
if spec then |
94 |
local parameters = {pos = pos, duration = subtitles.EPHEMERAL_DURATION}; |
95 |
subtitles.on_sound_play(spec, parameters, nil); |
96 |
end; |
97 |
end; |
98 |
|
99 |
|
100 |
--- Registers a description associated with a sound name. |
101 |
-- When this sound is played, it will have the specified description unless a |
102 |
-- description is explicitly specified. |
103 |
-- @param name The technical name of the sound, without the extension or index. |
104 |
-- @param description The human-readable description of the sound, or nil to not associate a description. |
105 |
-- @param parameters A table of parameters to override when playing this sound, or nil. |
106 |
function subtitles.register_description(name, description, parameters) |
107 |
if description then |
108 |
subtitles.registered_descriptions[name] = description; |
109 |
end; |
110 |
if parameters then |
111 |
local old_params = subtitles.registered_parameters[name] or {}; |
112 |
subtitles.registered_parameters[name] = subtitles.util.update(old_params, parameters); |
113 |
end; |
114 |
end; |
115 |
|
116 |
|
117 |
--- Reports a missing subtitle to the debug log. |
118 |
-- @param name The technical name of the sound. |
119 |
function subtitles.report_missing(name) |
120 |
if not subtitles.reported_missing[name] then |
121 |
subtitles.reported_missing[name] = true; |
122 |
minetest.log('warning', ('[Subtitles] No description available for sound ‘%s’.'):format(name)); |
123 |
end; |
124 |
end; |