The Battle for Wesnoth  1.19.14+dev
lua_audio.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "lua_audio.hpp"
16 
17 #include "log.hpp"
19 #include "resources.hpp"
20 #include "scripting/lua_common.hpp"
21 #include "scripting/push_check.hpp"
22 #include "sound.hpp"
23 #include "sound_music_track.hpp"
24 #include "soundsource.hpp"
25 #include <set>
26 #include <utility>
27 
28 static lg::log_domain log_audio("audio");
29 #define DBG_AUDIO LOG_STREAM(debug, log_audio)
30 #define LOG_AUDIO LOG_STREAM(info, log_audio)
31 #define ERR_AUDIO LOG_STREAM(err, log_audio)
32 
33 static const char* Track = "music track";
34 static const char* Source = "sound source";
35 
37  std::shared_ptr<sound::music_track> track;
38 public:
39  explicit lua_music_track(std::shared_ptr<sound::music_track>&& new_track) : track(std::move(new_track)) {}
41  return *track;
42  }
43  const sound::music_track& operator*() const {
44  return *track;
45  }
46  std::shared_ptr<sound::music_track> operator->() {
47  return track;
48  }
49  std::shared_ptr<const sound::music_track> operator->() const {
50  return track;
51  }
52 };
53 
54 static lua_music_track* push_track(lua_State* L, std::shared_ptr<sound::music_track>&& new_track) {
55  if(new_track) {
56  lua_music_track* trk = new(L) lua_music_track(std::move(new_track));
57  luaL_setmetatable(L, Track);
58  return trk;
59  } else {
60  lua_pushnil(L);
61  return nullptr;
62  }
63 }
64 
65 static lua_music_track* get_track(lua_State* L, int i) {
66  return static_cast<lua_music_track*>(luaL_checkudata(L, i, Track));
67 }
68 
71 public:
75  return spec;
76  }
78  return spec;
79  }
81  return &spec;
82  }
84  return &spec;
85  }
86 };
87 
88 static lua_sound_source& push_source(lua_State* L, const soundsource::sourcespec& spec) {
89  lua_sound_source* src = new(L) lua_sound_source(spec);
90  luaL_setmetatable(L, Source);
91  return *src;
92 }
93 
94 static lua_sound_source& get_source(lua_State* L, int i) {
95  return *static_cast<lua_sound_source*>(luaL_checkudata(L, i, Source));
96 }
97 
98 /**
99  * Destroys a lua_music_track object before it is collected (__gc metamethod).
100  */
101 static int impl_track_collect(lua_State* L)
102 {
103  lua_music_track* u = get_track(L, 1);
104  u->lua_music_track::~lua_music_track();
105  return 0;
106 }
107 
108 static int impl_music_get(lua_State* L) {
109  if(lua_isnumber(L, 2)) {
110  push_track(L, sound::get_track(lua_tointeger(L, 2) - 1));
111  return 1;
112  }
113  const char* m = luaL_checkstring(L, 2);
114 
115  if(strcmp(m, "current") == 0) {
117  return 1;
118  }
119 
120  if(strcmp(m, "previous") == 0) {
122  return 1;
123  }
124 
125  if(strcmp(m, "current_i") == 0) {
126  auto current_index = sound::get_current_track_index();
127  if(current_index) {
128  lua_pushinteger(L, *current_index + 1);
129  } else {
130  lua_pushnil(L);
131  }
132  return 1;
133  }
134  if(strcmp(m, "all") == 0) {
135  config playlist;
137  const auto& range = playlist.child_range("music");
138  std::vector<config> tracks(range.begin(), range.end());
139  lua_push(L, tracks);
140  return 1;
141  }
142  // This calculation reverses the one used in [volume] to get back the relative volume level.
143  // (Which is the same calculation that's duplicated in impl_music_set.)
145  return luaW_getmetafield(L, 1, m);
146 }
147 
148 static int impl_music_set(lua_State* L) {
149  if(lua_isnumber(L, 2)) {
150  unsigned int i = lua_tointeger(L, 2) - 1;
151  config cfg;
152  if(lua_isnil(L, 3)) {
153  if(i < sound::get_num_tracks()) {
155  }
156  } else if(luaW_toconfig(L, 3, cfg)) {
157  // Don't clear the playlist
158  cfg["append"] = true;
159  // Don't allow play_once=yes
160  if(cfg["play_once"].to_bool()) {
161  return luaL_argerror(L, 3, "For play_once, use wesnoth.music_list.play instead");
162  }
163  if(i >= sound::get_num_tracks()) {
165  } else {
166  // Remove the track at that index and add the new one in its place
167  // It's a little inefficient though...
169  sound::play_music_config(cfg, false, i);
170  }
171  } else {
172  lua_music_track& track = *get_track(L, 3);
173  if(i < sound::get_num_tracks()) {
174  sound::set_track(i, track.operator->());
175  } else {
176  track->write(cfg, true);
178  }
179  }
180  return 0;
181  }
182  const char* m = luaL_checkstring(L, 2);
183  modify_float_attrib_check_range("volume", sound::set_music_volume(value * prefs::get().music_volume() / 100.0), 0.0, 100.0);
184  modify_int_attrib_check_range("current_i", sound::play_track(value - 1), 1, static_cast<int>(sound::get_num_tracks()));
185  return 0;
186 }
187 
188 static int impl_music_len(lua_State* L) {
189  lua_pushinteger(L, sound::get_num_tracks());
190  return 1;
191 }
192 
193 static int intf_music_play(lua_State* L) {
194  sound::play_music_once(luaL_checkstring(L, 1));
195  return 0;
196 }
197 
198 static int intf_music_next(lua_State*) {
199  std::size_t n = sound::get_num_tracks();
200  if(n > 0) {
202  }
203  return 0;
204 }
205 
206 static int intf_music_add(lua_State* L) {
207  int index = -1;
208  if(lua_isinteger(L, 1)) {
209  index = lua_tointeger(L, 1);
210  lua_remove(L, 1);
211  }
212  config cfg = config {
213  "name", luaL_checkstring(L, 1),
214  "append", true,
215  };
216  bool found_ms_before = false, found_ms_after = false, found_imm = false;
217  for(int i = 2; i <= lua_gettop(L); i++) {
218  if(lua_isboolean(L, i)) {
219  if(found_imm) {
220  return luaL_argerror(L, i, "only one boolean argument may be passed");
221  } else {
222  cfg["immediate"] = luaW_toboolean(L, i);
223  }
224  } else if(lua_isnumber(L, i)) {
225  if(found_ms_after) {
226  return luaL_argerror(L, i, "only two integer arguments may be passed");
227  } else if(found_ms_before) {
228  cfg["ms_after"] = lua_tointeger(L, i);
229  found_ms_after = true;
230  } else {
231  cfg["ms_before"] = lua_tointeger(L, i);
232  found_ms_before = true;
233  }
234  } else {
235  return luaL_argerror(L, i, "unrecognized argument");
236  }
237  }
239  return 0;
240 }
241 
242 static int intf_music_clear(lua_State*) {
244  return 0;
245 }
246 
247 static int intf_music_remove(lua_State* L) {
248  // Use a non-standard comparator to ensure iteration in descending order
249  std::set<int, std::greater<int>> to_remove;
250  for(int i = 1; i <= lua_gettop(L); i++) {
251  to_remove.insert(luaL_checkinteger(L, i));
252  }
253  for(int i : to_remove) {
255  }
256  return 0;
257 }
258 
259 static int intf_music_commit(lua_State*) {
261  return 0;
262 }
263 
264 static int impl_track_get(lua_State* L) {
265  lua_music_track* track = get_track(L, 1);
266  if(track == nullptr) {
267  return luaL_error(L, "Error: Attempted to access an invalid music track.\n");
268  }
269  const char* m = luaL_checkstring(L, 2);
270  return_bool_attrib("append", (*track)->append());
271  return_bool_attrib("shuffle", (*track)->shuffle());
272  return_bool_attrib("immediate", (*track)->immediate());
273  return_bool_attrib("once", (*track)->play_once());
274  return_int_attrib("ms_before", (*track)->ms_before().count());
275  return_int_attrib("ms_after", (*track)->ms_after().count());
276  return_string_attrib("name", (*track)->id());
277  return_string_attrib("title", (*track)->title());
278 
279  return_cfg_attrib("__cfg",
280  cfg["append"]=(*track)->append();
281  cfg["shuffle"]=(*track)->shuffle();
282  cfg["immediate"]=(*track)->immediate();
283  cfg["once"]=(*track)->play_once();
284  cfg["ms_before"]=(*track)->ms_before();
285  cfg["ms_after"]=(*track)->ms_after();
286  cfg["name"]=(*track)->id();
287  cfg["title"]=(*track)->title());
288 
289  return luaW_getmetafield(L, 1, m);
290 }
291 
292 static int impl_track_set(lua_State* L) {
293  lua_music_track* track = get_track(L, 1);
294  if(track == nullptr) {
295  return luaL_error(L, "Error: Attempted to access an invalid music track.\n");
296  }
297  const char* m = luaL_checkstring(L, 2);
298  modify_bool_attrib("shuffle", (*track)->set_shuffle(value));
299  modify_bool_attrib("once", (*track)->set_play_once(value));
300  modify_int_attrib("ms_before", (*track)->set_ms_before(std::chrono::milliseconds{value}));
301  modify_int_attrib("ms_after", (*track)->set_ms_after(std::chrono::milliseconds{value}));
302  modify_string_attrib("title", (*track)->set_title(value));
303  return 0;
304 }
305 
306 static int impl_track_eq(lua_State* L) {
307  lua_music_track* a = get_track(L, 1);
308  lua_music_track* b = get_track(L, 2);
309  if(!a || !b) {
310  // This implies that one argument is not a music track, though I suspect this is dead code...?
311  // Does Lua ever call this if the arguments are not of the same type?
312  lua_pushboolean(L, false);
313  return 1;
314  }
315  lua_music_track& lhs = *a;
316  lua_music_track& rhs = *b;
317  lua_pushboolean(L, lhs->id() == rhs->id() && lhs->shuffle() == rhs->shuffle() && lhs->play_once() == rhs->play_once() && lhs->ms_before() == rhs->ms_before() && lhs->ms_after() == rhs->ms_after());
318  return 1;
319 }
320 
321 /**
322  * Get an existing sound source
323  * Key: The sound source ID
324  */
325 static int impl_sndsrc_get(lua_State* L) {
327  return 0;
328  }
329  std::string id = luaL_checkstring(L, 2);
331  return 0;
332  }
334  return 1;
335 }
336 
337 /**
338  * Adds or removes a sound source by its ID
339  * Key: sound source ID
340  * Value: Table containing keyword arguments, existing sound source userdata, or nil to delete
341  */
342 static int impl_sndsrc_set(lua_State* L) {
344  return 0;
345  }
346  std::string id = luaL_checkstring(L, 2);
347  config cfg;
348  if(lua_isnil(L, 3)) {
350  } else if(luaW_toconfig(L, 3, cfg)) {
351  cfg["id"] = id;
355  } else {
356  auto& src = get_source(L, 3);
359  }
360  return 0;
361 }
362 static int impl_source_collect(lua_State* L)
363 {
364  lua_sound_source& u = get_source(L, 1);
365  u.lua_sound_source::~lua_sound_source();
366  return 0;
367 }
368 
369 static int impl_source_get(lua_State* L) {
371  const char* m = luaL_checkstring(L, 2);
372  return_string_attrib("id", src->id());
373  return_vector_string_attrib("sounds", utils::split(src->files()));
374  return_int_attrib("delay", src->minimum_delay().count());
375  return_int_attrib("chance", src->chance());
376  return_int_attrib("loop", src->loops());
377  return_int_attrib("range", src->full_range());
378  return_int_attrib("fade_range", src->fade_range());
379  return_bool_attrib("check_fogged", src->check_fogged());
380  return_bool_attrib("check_shrouded", src->check_shrouded());
381  return_cfg_attrib("__cfg", src->write(cfg));
382 
383  if(strcmp(m, "locations") == 0) {
384  const auto& locs = src->get_locations();
385  lua_createtable(L, locs.size(), 0);
386  for(const auto& loc : locs) {
388  lua_rawseti(L, -1, lua_rawlen(L, -2) + 1);
389  }
390  }
391 
392  return luaW_getmetafield(L, 1, m);
393 }
394 
395 static int impl_source_set(lua_State* L) {
397  const char* m = luaL_checkstring(L, 2);
398  modify_int_attrib("delay", src->set_minimum_delay(std::chrono::milliseconds{value}));
399  modify_int_attrib("chance", src->set_chance(value));
400  modify_int_attrib("loop", src->set_loops(value));
401  modify_int_attrib("range", src->set_full_range(value));
402  modify_int_attrib("fade_range", src->set_fade_range(value));
403  modify_bool_attrib("check_fogged", src->set_check_fogged(value));
404  modify_bool_attrib("check_shrouded", src->set_check_shrouded(value));
405 
406  if(strcmp(m, "sounds") == 0) {
407  std::string files;
408  if(lua_istable(L, 3)) {
409  files = utils::join(lua_check<std::vector<std::string>>(L, 3));
410  } else {
411  files = luaL_checkstring(L, 3);
412  }
413  src->set_files(files);
414  }
415 
416  if(strcmp(m, "locations") == 0) {
417  std::vector<map_location> locs;
418  locs.resize(1);
419  if(luaW_tolocation(L, 3, locs[0])) {
420 
421  } else {
422  locs.clear();
423  for(lua_pushnil(L); lua_next(L, 3); lua_pop(L, 1)) {
424  locs.push_back(luaW_checklocation(L, -1));
425  }
426  }
427  src->set_locations(locs);
428  }
429 
430  // Now apply the change
433  return 0;
434 }
435 
436 static int impl_source_eq(lua_State* L) {
437  lua_sound_source& a = get_source(L, 1);
438  lua_sound_source& b = get_source(L, 2);
439  if(a->id() != b->id()) {
440  lua_pushboolean(L, false);
441  return 1;
442  }
443  lua_pushboolean(L,
444  a->files() == b->files() &&
445  a->minimum_delay() == b->minimum_delay() &&
446  a->chance() == b->chance() &&
447  a->loops() == b->loops() &&
448  a->full_range() == b->full_range() &&
449  a->fade_range() == b->fade_range() &&
450  a->check_fogged() == b->check_fogged() &&
451  a->check_shrouded() == b->check_shrouded() &&
452  std::set<map_location>(a->get_locations().begin(), a->get_locations().end()) == std::set<map_location>(b->get_locations().begin(), b->get_locations().end())
453  );
454  return 1;
455 }
456 
457 /**
458  * Gets the current sound volume
459  * - Return: Current volume
460  */
461 static int impl_audio_get(lua_State* L)
462 {
463  std::string m = luaL_checkstring(L, 2);
464  if(m != "volume") return 0;
465  int vol = prefs::get().sound_volume();
466  lua_pushnumber(L, sound::get_sound_volume() * 100.0 / vol);
467  return 1;
468 }
469 
470 /**
471  * Sets the current sound volume
472  * - Arg: New volume to set
473  */
474 static int impl_audio_set(lua_State* L)
475 {
476  std::string m = luaL_checkstring(L, 2);
477  if(m != "volume") {
478  lua_rawset(L, 1);
479  return 0;
480  }
481  int vol = prefs::get().sound_volume();
482  float rel = lua_tonumber(L, 3);
483  if(rel < 0.0f || rel > 100.0f) {
484  return luaL_argerror(L, 1, "volume must be in range 0..100");
485  }
486  vol = static_cast<int>(rel*vol / 100.0f);
488  return 0;
489 }
490 
491 namespace lua_audio {
492  std::string register_table(lua_State* L) {
493  // Metatable to enable the volume attribute
494  luaW_getglobal(L, "wesnoth", "audio");
495  lua_createtable(L, 0, 2);
496  static luaL_Reg vol_callbacks[] {
497  { "__index", impl_audio_get },
498  { "__newindex", impl_audio_set },
499  { nullptr, nullptr },
500  };
501  luaL_setfuncs(L, vol_callbacks, 0);
502  lua_setmetatable(L, -2);
503 
504  // The music playlist metatable
505  lua_newuserdatauv(L, 0, 0);
506  lua_createtable(L, 0, 10);
507  static luaL_Reg pl_callbacks[] {
508  { "__index", impl_music_get },
509  { "__newindex", impl_music_set },
510  { "__len", impl_music_len },
511  { "play", intf_music_play },
512  { "add", intf_music_add },
513  { "clear", intf_music_clear },
514  { "remove", intf_music_remove },
515  { "next", intf_music_next },
516  { "force_refresh", intf_music_commit },
517  { nullptr, nullptr },
518  };
519  luaL_setfuncs(L, pl_callbacks, 0);
520  lua_pushstring(L, "music playlist");
521  lua_setfield(L, -2, "__metatable");
522  lua_setmetatable(L, -2);
523  lua_setfield(L, -2, "music_list");
524 
525  // The sound source map metatable
526  lua_newuserdatauv(L, 0, 0);
527  lua_createtable(L, 0, 3);
528  static luaL_Reg slm_callbacks[] {
529  { "__index", impl_sndsrc_get },
530  { "__newindex", impl_sndsrc_set },
531  { nullptr, nullptr },
532  };
533  luaL_setfuncs(L, slm_callbacks, 0);
534  lua_pushstring(L, "sound source map");
535  lua_setfield(L, -2, "__metatable");
536  lua_setmetatable(L, -2);
537  lua_setfield(L, -2, "sources");
538  lua_pop(L, 1);
539 
540  // The music track metatable
541  luaL_newmetatable(L, Track);
542  static luaL_Reg track_callbacks[] {
543  {"__gc", impl_track_collect},
544  { "__index", impl_track_get },
545  { "__newindex", impl_track_set },
546  { "__eq", impl_track_eq },
547  { nullptr, nullptr },
548  };
549  luaL_setfuncs(L, track_callbacks, 0);
550  lua_pushstring(L, Track);
551  lua_setfield(L, -2, "__metatable");
552  lua_pop(L, 1);
553 
554  // The sound source metatable
555  luaL_newmetatable(L, Source);
556  static luaL_Reg source_callbacks[] {
557  {"__gc", impl_source_collect},
558  { "__index", impl_source_get },
559  { "__newindex", impl_source_set },
560  { "__eq", impl_source_eq },
561  { nullptr, nullptr },
562  };
563  luaL_setfuncs(L, source_callbacks, 0);
564  lua_pushstring(L, Source);
565  lua_setfield(L, -2, "__metatable");
566 
567  return "Adding music playlist table...\n";
568  }
569 }
map_location loc
Definition: move.cpp:172
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:188
child_itors child_range(config_key_type key)
Definition: config.cpp:268
lua_music_track(std::shared_ptr< sound::music_track > &&new_track)
Definition: lua_audio.cpp:39
const sound::music_track & operator*() const
Definition: lua_audio.cpp:43
std::shared_ptr< sound::music_track > operator->()
Definition: lua_audio.cpp:46
std::shared_ptr< const sound::music_track > operator->() const
Definition: lua_audio.cpp:49
sound::music_track & operator*()
Definition: lua_audio.cpp:40
std::shared_ptr< sound::music_track > track
Definition: lua_audio.cpp:37
soundsource::sourcespec & operator*()
Definition: lua_audio.cpp:74
lua_sound_source(lua_sound_source &)=delete
soundsource::sourcespec spec
Definition: lua_audio.cpp:70
lua_sound_source(const soundsource::sourcespec &spec)
Definition: lua_audio.cpp:72
const soundsource::sourcespec & operator*() const
Definition: lua_audio.cpp:77
const soundsource::sourcespec * operator->() const
Definition: lua_audio.cpp:83
soundsource::sourcespec * operator->()
Definition: lua_audio.cpp:80
static prefs & get()
int sound_volume()
Internal representation of music tracks.
void add(const sourcespec &source)
Definition: soundsource.cpp:50
void remove(const std::string &id)
Definition: soundsource.cpp:65
Sound source info class.
const std::vector< map_location > & get_locations() const
const std::string & files() const
bool check_shrouded() const
auto minimum_delay() const
const std::string & id() const
const config * cfg
std::size_t i
Definition: function.cpp:1032
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:199
Standard logging facilities (interface).
std::decay_t< T > lua_check(lua_State *L, int n)
Definition: push_check.hpp:411
static int intf_music_add(lua_State *L)
Definition: lua_audio.cpp:206
static lua_sound_source & push_source(lua_State *L, const soundsource::sourcespec &spec)
Definition: lua_audio.cpp:88
static int impl_audio_set(lua_State *L)
Sets the current sound volume.
Definition: lua_audio.cpp:474
static int impl_source_collect(lua_State *L)
Definition: lua_audio.cpp:362
static const char * Track
Definition: lua_audio.cpp:33
static int impl_music_len(lua_State *L)
Definition: lua_audio.cpp:188
static int impl_track_set(lua_State *L)
Definition: lua_audio.cpp:292
static int intf_music_commit(lua_State *)
Definition: lua_audio.cpp:259
static lua_music_track * get_track(lua_State *L, int i)
Definition: lua_audio.cpp:65
static int impl_music_get(lua_State *L)
Definition: lua_audio.cpp:108
static int intf_music_remove(lua_State *L)
Definition: lua_audio.cpp:247
static int impl_audio_get(lua_State *L)
Gets the current sound volume.
Definition: lua_audio.cpp:461
static lg::log_domain log_audio("audio")
static int impl_track_get(lua_State *L)
Definition: lua_audio.cpp:264
static lua_sound_source & get_source(lua_State *L, int i)
Definition: lua_audio.cpp:94
static int impl_source_eq(lua_State *L)
Definition: lua_audio.cpp:436
static int impl_source_set(lua_State *L)
Definition: lua_audio.cpp:395
static int intf_music_next(lua_State *)
Definition: lua_audio.cpp:198
static int intf_music_play(lua_State *L)
Definition: lua_audio.cpp:193
static int impl_track_eq(lua_State *L)
Definition: lua_audio.cpp:306
static int impl_source_get(lua_State *L)
Definition: lua_audio.cpp:369
static int impl_sndsrc_set(lua_State *L)
Adds or removes a sound source by its ID Key: sound source ID Value: Table containing keyword argumen...
Definition: lua_audio.cpp:342
static const char * Source
Definition: lua_audio.cpp:34
static int impl_sndsrc_get(lua_State *L)
Get an existing sound source Key: The sound source ID.
Definition: lua_audio.cpp:325
static int impl_track_collect(lua_State *L)
Destroys a lua_music_track object before it is collected (__gc metamethod).
Definition: lua_audio.cpp:101
static int impl_music_set(lua_State *L)
Definition: lua_audio.cpp:148
static lua_music_track * push_track(lua_State *L, std::shared_ptr< sound::music_track > &&new_track)
Definition: lua_audio.cpp:54
static int intf_music_clear(lua_State *)
Definition: lua_audio.cpp:242
void luaW_pushlocation(lua_State *L, const map_location &ml)
Converts a map location object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:808
bool luaW_toboolean(lua_State *L, int n)
bool luaW_getmetafield(lua_State *L, int idx, const char *key)
Like luaL_getmetafield, but returns false if key is an empty string or begins with two underscores.
Definition: lua_common.cpp:524
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:934
bool luaW_tolocation(lua_State *L, int index, map_location &loc)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:819
map_location luaW_checklocation(lua_State *L, int index)
Converts an optional table or pair of integers to a map location object.
Definition: lua_common.cpp:868
bool luaW_getglobal(lua_State *L, const std::vector< std::string > &path)
Pushes the value found by following the variadic names (char *), if the value is not nil.
#define return_float_attrib(name, accessor)
Definition: lua_common.hpp:287
#define return_vector_string_attrib(name, accessor)
Definition: lua_common.hpp:329
#define return_string_attrib(name, accessor)
Definition: lua_common.hpp:266
#define return_int_attrib(name, accessor)
Definition: lua_common.hpp:277
#define modify_bool_attrib(name, accessor)
Definition: lua_common.hpp:414
#define return_bool_attrib(name, accessor)
Definition: lua_common.hpp:297
#define modify_int_attrib(name, accessor)
Definition: lua_common.hpp:368
#define return_cfg_attrib(name, accessor)
Definition: lua_common.hpp:307
#define modify_float_attrib_check_range(name, accessor, allowed_min, allowed_max)
Definition: lua_common.hpp:402
#define modify_string_attrib(name, accessor)
Definition: lua_common.hpp:357
#define modify_int_attrib_check_range(name, accessor, allowed_min, allowed_max)
Definition: lua_common.hpp:379
CURSOR_TYPE get()
Definition: cursor.cpp:218
static int music_volume()
std::string register_table(lua_State *L)
Definition: lua_audio.cpp:492
soundsource::manager * soundsources
Definition: resources.cpp:27
void write_music_play_list(config &snapshot)
Definition: sound.cpp:846
void empty_playlist()
Definition: sound.cpp:611
int get_music_volume()
Definition: sound.cpp:1058
void play_music_config(const config &music_node, bool allow_interrupt_current_track, int i)
Definition: sound.cpp:689
void remove_track(unsigned int i)
Definition: sound.cpp:243
unsigned int get_num_tracks()
Definition: sound.cpp:218
void play_music_once(const std::string &file)
Definition: sound.cpp:600
utils::optional< unsigned int > get_current_track_index()
Definition: sound.cpp:198
void set_track(unsigned int i, const std::shared_ptr< music_track > &to)
Definition: sound.cpp:236
int get_sound_volume()
Definition: sound.cpp:1078
void commit_music_changes()
Definition: sound.cpp:817
void play_track(unsigned int i)
Definition: sound.cpp:628
std::shared_ptr< music_track > get_previous_music_track()
Definition: sound.cpp:209
void set_music_volume(int vol)
Definition: sound.cpp:1067
std::shared_ptr< music_track > get_track(unsigned int i)
Definition: sound.cpp:223
std::shared_ptr< music_track > get_current_track()
Definition: sound.cpp:205
void set_sound_volume(int vol)
Definition: sound.cpp:1087
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:87
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::vector< std::string > split(const config_attribute_value &val)
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:425
rect src
Non-transparent portion of the surface to compose.
static map_location::direction n
#define b