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