OpenTTD
music_gui.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include <vector>
12 #include "openttd.h"
13 #include "base_media_base.h"
14 #include "music/music_driver.hpp"
15 #include "window_gui.h"
16 #include "strings_func.h"
17 #include "window_func.h"
18 #include "sound_func.h"
19 #include "gfx_func.h"
20 #include "zoom_func.h"
21 #include "core/random_func.hpp"
22 #include "error.h"
23 #include "core/geometry_func.hpp"
24 #include "string_func.h"
25 #include "settings_type.h"
26 #include "settings_gui.h"
27 #include "widgets/dropdown_func.h"
28 #include "widgets/dropdown_type.h"
29 
30 #include "widgets/music_widget.h"
31 
32 #include "table/strings.h"
33 #include "table/sprites.h"
34 
35 #include "safeguards.h"
36 
37 
38 struct MusicSystem {
40  const MusicSet *set;
41  uint set_index;
42 
43  PlaylistEntry(const MusicSet *set, uint set_index) : MusicSongInfo(set->songinfo[set_index]), set(set), set_index(set_index) { }
44  bool IsValid() const { return !StrEmpty(this->songname); }
45  };
46  typedef std::vector<PlaylistEntry> Playlist;
47 
48  enum PlaylistChoices {
49  PLCH_ALLMUSIC,
50  PLCH_OLDSTYLE,
51  PLCH_NEWSTYLE,
52  PLCH_EZYSTREET,
53  PLCH_CUSTOM1,
54  PLCH_CUSTOM2,
55  PLCH_THEMEONLY,
56  PLCH_MAX,
57  };
58 
59  Playlist active_playlist;
60  Playlist displayed_playlist;
61  Playlist music_set;
62 
63  PlaylistChoices selected_playlist;
64 
65  void BuildPlaylists();
66 
67  void ChangePlaylist(PlaylistChoices pl);
68  void ChangeMusicSet(const char *set_name);
69  void Shuffle();
70  void Unshuffle();
71 
72  void Play();
73  void Stop();
74  void Next();
75  void Prev();
76  void CheckStatus();
77 
78  bool IsPlaying() const;
79  bool IsShuffle() const;
81 
82  bool IsCustomPlaylist() const;
83  void PlaylistAdd(size_t song_index);
84  void PlaylistRemove(size_t song_index);
85  void PlaylistClear();
86 
87 private:
88  void ChangePlaylistPosition(int ofs);
89  int playlist_position;
90 
91  void SaveCustomPlaylist(PlaylistChoices pl);
92 
93  Playlist standard_playlists[PLCH_MAX];
94 };
95 
96 MusicSystem _music;
97 
98 
101 {
102  const MusicSet *set = BaseMusic::GetUsedSet();
103 
104  /* Clear current playlists */
105  for (size_t i = 0; i < lengthof(this->standard_playlists); ++i) this->standard_playlists[i].clear();
106  this->music_set.clear();
107 
108  /* Build standard playlists, and a list of available music */
109  for (uint i = 0; i < NUM_SONGS_AVAILABLE; i++) {
110  PlaylistEntry entry(set, i);
111  if (!entry.IsValid()) continue;
112 
113  this->music_set.push_back(entry);
114 
115  /* Add theme song to theme-only playlist */
116  if (i == 0) this->standard_playlists[PLCH_THEMEONLY].push_back(entry);
117 
118  /* Don't add the theme song to standard playlists */
119  if (i > 0) {
120  this->standard_playlists[PLCH_ALLMUSIC].push_back(entry);
121  uint theme = (i - 1) / NUM_SONGS_CLASS;
122  this->standard_playlists[PLCH_OLDSTYLE + theme].push_back(entry);
123  }
124  }
125 
126  /* Load custom playlists
127  * Song index offsets are 1-based, zero indicates invalid/end-of-list value */
128  for (uint i = 0; i < NUM_SONGS_PLAYLIST; i++) {
129  if (_settings_client.music.custom_1[i] > 0) {
130  PlaylistEntry entry(set, _settings_client.music.custom_1[i] - 1);
131  if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM1].push_back(entry);
132  }
133  if (_settings_client.music.custom_2[i] > 0) {
134  PlaylistEntry entry(set, _settings_client.music.custom_2[i] - 1);
135  if (entry.IsValid()) this->standard_playlists[PLCH_CUSTOM2].push_back(entry);
136  }
137  }
138 }
139 
144 void MusicSystem::ChangePlaylist(PlaylistChoices pl)
145 {
146  assert(pl < PLCH_MAX && pl >= PLCH_ALLMUSIC);
147 
148  this->displayed_playlist = this->standard_playlists[pl];
149  this->active_playlist = this->displayed_playlist;
150  this->selected_playlist = pl;
151  this->playlist_position = 0;
152 
153  if (this->selected_playlist != PLCH_THEMEONLY) _settings_client.music.playlist = this->selected_playlist;
154 
156  this->Shuffle();
157  /* Shuffle() will also Play() if necessary, only start once */
158  } else if (_settings_client.music.playing) {
159  this->Play();
160  }
161 
164 }
165 
170 void MusicSystem::ChangeMusicSet(const char *set_name)
171 {
172  BaseMusic::SetSet(set_name);
173 
175  BaseMusic::ini_set = stredup(set_name);
176 
177  this->BuildPlaylists();
178  this->ChangePlaylist(this->selected_playlist);
179 
181 }
182 
185 {
187 
188  this->active_playlist = this->displayed_playlist;
189  for (size_t i = 0; i < this->active_playlist.size(); i++) {
190  size_t shuffle_index = InteractiveRandom() % (this->active_playlist.size() - i);
191  std::swap(this->active_playlist[i], this->active_playlist[i + shuffle_index]);
192  }
193 
194  if (_settings_client.music.playing) this->Play();
195 
197 }
198 
201 {
203  this->active_playlist = this->displayed_playlist;
204 
205  if (_settings_client.music.playing) this->Play();
206 
208 }
209 
212 {
213  /* Always set the playing flag, even if there is no music */
216  /* Make sure playlist_position is a valid index, if playlist has changed etc. */
217  this->ChangePlaylistPosition(0);
218 
219  /* If there is no music, don't try to play it */
220  if (this->active_playlist.empty()) return;
221 
222  MusicSongInfo song = this->active_playlist[this->playlist_position];
223  if (_game_mode == GM_MENU && this->selected_playlist == PLCH_THEMEONLY) song.loop = true;
225 
227 }
228 
231 {
234 
236 }
237 
240 {
241  this->ChangePlaylistPosition(+1);
242  if (_settings_client.music.playing) this->Play();
243 
245 }
246 
249 {
250  this->ChangePlaylistPosition(-1);
251  if (_settings_client.music.playing) this->Play();
252 
254 }
255 
258 {
259  if ((_game_mode == GM_MENU) != (this->selected_playlist == PLCH_THEMEONLY)) {
260  /* Make sure the theme-only playlist is active when on the title screen, and not during gameplay */
261  this->ChangePlaylist((_game_mode == GM_MENU) ? PLCH_THEMEONLY : (PlaylistChoices)_settings_client.music.playlist);
262  }
263  if (this->active_playlist.empty()) return;
264  /* If we were supposed to be playing, but music has stopped, move to next song */
265  if (this->IsPlaying() && !MusicDriver::GetInstance()->IsSongPlaying()) this->Next();
266 }
267 
270 {
271  return _settings_client.music.playing && !this->active_playlist.empty();
272 }
273 
276 {
278 }
279 
282 {
283  if (!this->IsPlaying()) return PlaylistEntry(BaseMusic::GetUsedSet(), 0);
284  return this->active_playlist[this->playlist_position];
285 }
286 
289 {
290  return (this->selected_playlist == PLCH_CUSTOM1) || (this->selected_playlist == PLCH_CUSTOM2);
291 }
292 
298 void MusicSystem::PlaylistAdd(size_t song_index)
299 {
300  if (!this->IsCustomPlaylist()) return;
301 
302  /* Pick out song from the music set */
303  if (song_index >= this->music_set.size()) return;
304  PlaylistEntry entry = this->music_set[song_index];
305 
306  /* Check for maximum length */
307  if (this->standard_playlists[this->selected_playlist].size() >= NUM_SONGS_PLAYLIST) return;
308 
309  /* Add it to the appropriate playlist, and the display */
310  this->standard_playlists[this->selected_playlist].push_back(entry);
311  this->displayed_playlist.push_back(entry);
312 
313  /* Add it to the active playlist, if playback is shuffled select a random position to add at */
314  if (this->active_playlist.empty()) {
315  this->active_playlist.push_back(entry);
316  if (this->IsPlaying()) this->Play();
317  } else if (this->IsShuffle()) {
318  /* Generate a random position between 0 and n (inclusive, new length) to insert at */
319  size_t maxpos = this->displayed_playlist.size();
320  size_t newpos = InteractiveRandom() % maxpos;
321  this->active_playlist.insert(this->active_playlist.begin() + newpos, entry);
322  /* Make sure to shift up the current playback position if the song was inserted before it */
323  if ((int)newpos <= this->playlist_position) this->playlist_position++;
324  } else {
325  this->active_playlist.push_back(entry);
326  }
327 
328  this->SaveCustomPlaylist(this->selected_playlist);
329 
331 }
332 
337 void MusicSystem::PlaylistRemove(size_t song_index)
338 {
339  if (!this->IsCustomPlaylist()) return;
340 
341  Playlist &pl = this->standard_playlists[this->selected_playlist];
342  if (song_index >= pl.size()) return;
343 
344  /* Remove from "simple" playlists */
345  PlaylistEntry song = pl[song_index];
346  pl.erase(pl.begin() + song_index);
347  this->displayed_playlist.erase(this->displayed_playlist.begin() + song_index);
348 
349  /* Find in actual active playlist (may be shuffled) and remove,
350  * if it's the current song restart playback */
351  for (size_t i = 0; i < this->active_playlist.size(); i++) {
352  Playlist::iterator s2 = this->active_playlist.begin() + i;
353  if (s2->filename == song.filename && s2->cat_index == song.cat_index) {
354  this->active_playlist.erase(s2);
355  if ((int)i == this->playlist_position && this->IsPlaying()) this->Play();
356  break;
357  }
358  }
359 
360  this->SaveCustomPlaylist(this->selected_playlist);
361 
363 }
364 
370 {
371  if (!this->IsCustomPlaylist()) return;
372 
373  this->standard_playlists[this->selected_playlist].clear();
374  this->ChangePlaylist(this->selected_playlist);
375 
376  this->SaveCustomPlaylist(this->selected_playlist);
377 }
378 
385 {
386  if (this->active_playlist.empty()) {
387  this->playlist_position = 0;
388  } else {
389  this->playlist_position += ofs;
390  while (this->playlist_position >= (int)this->active_playlist.size()) this->playlist_position -= (int)this->active_playlist.size();
391  while (this->playlist_position < 0) this->playlist_position += (int)this->active_playlist.size();
392  }
393 }
394 
399 void MusicSystem::SaveCustomPlaylist(PlaylistChoices pl)
400 {
401  byte *settings_pl;
402  if (pl == PLCH_CUSTOM1) {
403  settings_pl = _settings_client.music.custom_1;
404  } else if (pl == PLCH_CUSTOM2) {
405  settings_pl = _settings_client.music.custom_2;
406  } else {
407  return;
408  }
409 
410  size_t num = 0;
411  MemSetT(settings_pl, 0, NUM_SONGS_PLAYLIST);
412 
413  for (Playlist::const_iterator song = this->standard_playlists[pl].begin(); song != this->standard_playlists[pl].end(); ++song) {
414  /* Music set indices in the settings playlist are 1-based, 0 means unused slot */
415  settings_pl[num++] = (byte)song->set_index + 1;
416  }
417 }
418 
419 
424 void MusicLoop()
425 {
426  _music.CheckStatus();
427 }
428 
433 void ChangeMusicSet(int index)
434 {
435  if (BaseMusic::GetIndexOfUsedSet() == index) return;
436  const char *name = BaseMusic::GetSet(index)->name;
437  _music.ChangeMusicSet(name);
438 }
439 
445 {
446  _music.BuildPlaylists();
447 }
448 
449 
452  {
453  this->InitNested(number);
454  this->LowerWidget(WID_MTS_LIST_LEFT);
455  this->LowerWidget(WID_MTS_LIST_RIGHT);
456  this->SetWidgetDisabledState(WID_MTS_CLEAR, _settings_client.music.playlist <= 3);
457  this->LowerWidget(WID_MTS_ALL + _settings_client.music.playlist);
458  }
459 
460  void SetStringParameters(int widget) const override
461  {
462  switch (widget) {
463  case WID_MTS_PLAYLIST:
464  SetDParam(0, STR_MUSIC_PLAYLIST_ALL + _settings_client.music.playlist);
465  break;
466  case WID_MTS_CAPTION:
468  break;
469  }
470  }
471 
477  void OnInvalidateData(int data = 0, bool gui_scope = true) override
478  {
479  if (!gui_scope) return;
480  for (int i = 0; i < 6; i++) {
481  this->SetWidgetLoweredState(WID_MTS_ALL + i, i == _settings_client.music.playlist);
482  }
483  this->SetWidgetDisabledState(WID_MTS_CLEAR, _settings_client.music.playlist <= 3);
484  this->SetDirty();
485  }
486 
487  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
488  {
489  switch (widget) {
490  case WID_MTS_PLAYLIST: {
491  Dimension d = {0, 0};
492 
493  for (int i = 0; i < 6; i++) {
494  SetDParam(0, STR_MUSIC_PLAYLIST_ALL + i);
495  d = maxdim(d, GetStringBoundingBox(STR_PLAYLIST_PROGRAM));
496  }
497  d.width += padding.width;
498  d.height += padding.height;
499  *size = maxdim(*size, d);
500  break;
501  }
502 
504  Dimension d = {0, 0};
505 
506  for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) {
507  SetDParam(0, song->tracknr);
508  SetDParam(1, 2);
509  SetDParamStr(2, song->songname);
510  Dimension d2 = GetStringBoundingBox(STR_PLAYLIST_TRACK_NAME);
511  d.width = max(d.width, d2.width);
512  d.height += d2.height;
513  }
514  d.width += padding.width;
515  d.height += padding.height;
516  *size = maxdim(*size, d);
517  break;
518  }
519  }
520  }
521 
522  void DrawWidget(const Rect &r, int widget) const override
523  {
524  switch (widget) {
525  case WID_MTS_LIST_LEFT: {
526  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK);
527 
528  int y = r.top + WD_FRAMERECT_TOP;
529  for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) {
530  SetDParam(0, song->tracknr);
531  SetDParam(1, 2);
532  SetDParamStr(2, song->songname);
533  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
534  y += FONT_HEIGHT_SMALL;
535  }
536  break;
537  }
538 
539  case WID_MTS_LIST_RIGHT: {
540  GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, PC_BLACK);
541 
542  int y = r.top + WD_FRAMERECT_TOP;
543  for (MusicSystem::Playlist::const_iterator song = _music.active_playlist.begin(); song != _music.active_playlist.end(); ++song) {
544  SetDParam(0, song->tracknr);
545  SetDParam(1, 2);
546  SetDParamStr(2, song->songname);
547  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_PLAYLIST_TRACK_NAME);
548  y += FONT_HEIGHT_SMALL;
549  }
550  break;
551  }
552  }
553  }
554 
555  void OnClick(Point pt, int widget, int click_count) override
556  {
557  switch (widget) {
558  case WID_MTS_LIST_LEFT: { // add to playlist
559  int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
560  _music.PlaylistAdd(y);
561  break;
562  }
563 
564  case WID_MTS_LIST_RIGHT: { // remove from playlist
565  int y = this->GetRowFromWidget(pt.y, widget, 0, FONT_HEIGHT_SMALL);
566  _music.PlaylistRemove(y);
567  break;
568  }
569 
570  case WID_MTS_MUSICSET: {
571  int selected = 0;
572  ShowDropDownList(this, BuildMusicSetDropDownList(&selected), selected, widget, 0, true, false);
573  break;
574  }
575 
576  case WID_MTS_CLEAR: // clear
577  _music.PlaylistClear();
578  break;
579 
580  case WID_MTS_ALL: case WID_MTS_OLD: case WID_MTS_NEW:
581  case WID_MTS_EZY: case WID_MTS_CUSTOM1: case WID_MTS_CUSTOM2: // set playlist
582  _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_MTS_ALL));
583  break;
584  }
585  }
586 
587  void OnDropdownSelect(int widget, int index) override
588  {
589  switch (widget) {
590  case WID_MTS_MUSICSET:
591  ChangeMusicSet(index);
592  break;
593  default:
594  NOT_REACHED();
595  }
596  }
597 };
598 
599 static const NWidgetPart _nested_music_track_selection_widgets[] = {
601  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
602  NWidget(WWT_CAPTION, COLOUR_GREY, WID_MTS_CAPTION), SetDataTip(STR_PLAYLIST_MUSIC_SELECTION_SETNAME, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
603  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_MTS_MUSICSET), SetDataTip(STR_PLAYLIST_CHANGE_SET, STR_PLAYLIST_TOOLTIP_CHANGE_SET),
604  EndContainer(),
605  NWidget(WWT_PANEL, COLOUR_GREY),
606  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
607  /* Left panel. */
609  NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_PLAYLIST_TRACK_INDEX, STR_NULL),
610  NWidget(WWT_PANEL, COLOUR_GREY, WID_MTS_LIST_LEFT), SetMinimalSize(180, 194), SetDataTip(0x0, STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK), EndContainer(),
612  EndContainer(),
613  /* Middle buttons. */
615  NWidget(NWID_SPACER), SetMinimalSize(60, 30), // Space above the first button from the title bar.
616  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_ALL), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_ALL, STR_MUSIC_TOOLTIP_SELECT_ALL_TRACKS_PROGRAM),
617  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_OLD), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_OLD_STYLE, STR_MUSIC_TOOLTIP_SELECT_OLD_STYLE_MUSIC),
618  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_NEW), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_NEW_STYLE, STR_MUSIC_TOOLTIP_SELECT_NEW_STYLE_MUSIC),
619  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_EZY), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_EZY_STREET, STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE),
620  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM1), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_1, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED),
621  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_MTS_CUSTOM2), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_2, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED),
622  NWidget(NWID_SPACER), SetMinimalSize(0, 16), // Space above 'clear' button
623  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_MTS_CLEAR), SetFill(1, 0), SetDataTip(STR_PLAYLIST_CLEAR, STR_PLAYLIST_TOOLTIP_CLEAR_CURRENT_PROGRAM_CUSTOM1),
624  NWidget(NWID_SPACER), SetFill(0, 1),
625  EndContainer(),
626  /* Right panel. */
628  NWidget(WWT_LABEL, COLOUR_GREY, WID_MTS_PLAYLIST), SetDataTip(STR_PLAYLIST_PROGRAM, STR_NULL),
629  NWidget(WWT_PANEL, COLOUR_GREY, WID_MTS_LIST_RIGHT), SetMinimalSize(180, 194), SetDataTip(0x0, STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK), EndContainer(),
631  EndContainer(),
632  EndContainer(),
633  EndContainer(),
634 };
635 
636 static WindowDesc _music_track_selection_desc(
637  WDP_AUTO, "music_track", 0, 0,
639  0,
640  _nested_music_track_selection_widgets, lengthof(_nested_music_track_selection_widgets)
641 );
642 
643 static void ShowMusicTrackSelection()
644 {
645  AllocateWindowDescFront<MusicTrackSelectionWindow>(&_music_track_selection_desc, 0);
646 }
647 
648 struct MusicWindow : public Window {
649  static const int slider_width = 3;
650 
651  MusicWindow(WindowDesc *desc, WindowNumber number) : Window(desc)
652  {
653  this->InitNested(number);
654  this->LowerWidget(_settings_client.music.playlist + WID_M_ALL);
655  this->SetWidgetLoweredState(WID_M_SHUFFLE, _settings_client.music.shuffle);
656 
657  UpdateDisabledButtons();
658  }
659 
660  void UpdateDisabledButtons()
661  {
662  /* Disable music control widgets if there is no music
663  * -- except Programme button! So you can still select a music set. */
664  this->SetWidgetsDisabledState(
665  BaseMusic::GetUsedSet()->num_available == 0,
669  );
670  }
671 
672  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
673  {
674  switch (widget) {
675  /* Make sure that WID_M_SHUFFLE and WID_M_PROGRAMME have the same size.
676  * This can't be done by using NC_EQUALSIZE as the WID_M_INFO is
677  * between those widgets and of different size. */
678  case WID_M_SHUFFLE: case WID_M_PROGRAMME: {
679  Dimension d = maxdim(GetStringBoundingBox(STR_MUSIC_PROGRAM), GetStringBoundingBox(STR_MUSIC_SHUFFLE));
680  d.width += padding.width;
681  d.height += padding.height;
682  *size = maxdim(*size, d);
683  break;
684  }
685 
686  case WID_M_TRACK_NR: {
687  Dimension d = GetStringBoundingBox(STR_MUSIC_TRACK_NONE);
690  *size = maxdim(*size, d);
691  break;
692  }
693 
694  case WID_M_TRACK_NAME: {
695  Dimension d = GetStringBoundingBox(STR_MUSIC_TITLE_NONE);
696  for (MusicSystem::Playlist::const_iterator song = _music.music_set.begin(); song != _music.music_set.end(); ++song) {
697  SetDParamStr(0, song->songname);
698  d = maxdim(d, GetStringBoundingBox(STR_MUSIC_TITLE_NAME));
699  }
702  *size = maxdim(*size, d);
703  break;
704  }
705 
706  /* Hack-ish: set the proper widget data; only needs to be done once
707  * per (Re)Init as that's the only time the language changes. */
708  case WID_M_PREV: this->GetWidget<NWidgetCore>(WID_M_PREV)->widget_data = _current_text_dir == TD_RTL ? SPR_IMG_SKIP_TO_NEXT : SPR_IMG_SKIP_TO_PREV; break;
709  case WID_M_NEXT: this->GetWidget<NWidgetCore>(WID_M_NEXT)->widget_data = _current_text_dir == TD_RTL ? SPR_IMG_SKIP_TO_PREV : SPR_IMG_SKIP_TO_NEXT; break;
710  case WID_M_PLAY: this->GetWidget<NWidgetCore>(WID_M_PLAY)->widget_data = _current_text_dir == TD_RTL ? SPR_IMG_PLAY_MUSIC_RTL : SPR_IMG_PLAY_MUSIC; break;
711  }
712  }
713 
714  void DrawWidget(const Rect &r, int widget) const override
715  {
716  switch (widget) {
717  case WID_M_TRACK_NR: {
718  GfxFillRect(r.left + 1, r.top + 1, r.right, r.bottom, PC_BLACK);
719  if (BaseMusic::GetUsedSet()->num_available == 0) {
720  break;
721  }
722  StringID str = STR_MUSIC_TRACK_NONE;
723  if (_music.IsPlaying()) {
724  SetDParam(0, _music.GetCurrentSong().tracknr);
725  SetDParam(1, 2);
726  str = STR_MUSIC_TRACK_DIGIT;
727  }
728  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str);
729  break;
730  }
731 
732  case WID_M_TRACK_NAME: {
733  GfxFillRect(r.left, r.top + 1, r.right - 1, r.bottom, PC_BLACK);
734  StringID str = STR_MUSIC_TITLE_NONE;
735  if (BaseMusic::GetUsedSet()->num_available == 0) {
736  str = STR_MUSIC_TITLE_NOMUSIC;
737  } else if (_music.IsPlaying()) {
738  str = STR_MUSIC_TITLE_NAME;
739  SetDParamStr(0, _music.GetCurrentSong().songname);
740  }
741  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_FROMSTRING, SA_HOR_CENTER);
742  break;
743  }
744 
745  case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: {
746  int sw = ScaleGUITrad(slider_width);
747  int hsw = sw / 2;
748  DrawFrameRect(r.left + hsw, r.top + 2, r.right - hsw, r.bottom - 2, COLOUR_GREY, FR_LOWERED);
750  if (_current_text_dir == TD_RTL) volume = 127 - volume;
751  int x = r.left + (volume * (r.right - r.left - sw) / 127);
752  DrawFrameRect(x, r.top, x + sw, r.bottom, COLOUR_GREY, FR_NONE);
753  break;
754  }
755  }
756  }
757 
763  void OnInvalidateData(int data = 0, bool gui_scope = true) override
764  {
765  if (!gui_scope) return;
766  for (int i = 0; i < 6; i++) {
767  this->SetWidgetLoweredState(WID_M_ALL + i, i == _settings_client.music.playlist);
768  }
769 
770  UpdateDisabledButtons();
771 
772  this->SetDirty();
773  }
774 
775  void OnClick(Point pt, int widget, int click_count) override
776  {
777  switch (widget) {
778  case WID_M_PREV: // skip to prev
779  _music.Prev();
780  break;
781 
782  case WID_M_NEXT: // skip to next
783  _music.Next();
784  break;
785 
786  case WID_M_STOP: // stop playing
787  _music.Stop();
788  break;
789 
790  case WID_M_PLAY: // start playing
791  _music.Play();
792  break;
793 
794  case WID_M_MUSIC_VOL: case WID_M_EFFECT_VOL: { // volume sliders
795  int x = pt.x - this->GetWidget<NWidgetBase>(widget)->pos_x;
796 
798 
799  byte new_vol = Clamp(x * 127 / (int)this->GetWidget<NWidgetBase>(widget)->current_x, 0, 127);
800  if (_current_text_dir == TD_RTL) new_vol = 127 - new_vol;
801  /* Clamp to make sure min and max are properly settable */
802  if (new_vol > 124) new_vol = 127;
803  if (new_vol < 3) new_vol = 0;
804  if (new_vol != *vol) {
805  *vol = new_vol;
806  if (widget == WID_M_MUSIC_VOL) MusicDriver::GetInstance()->SetVolume(new_vol);
807  this->SetDirty();
808  }
809 
810  if (click_count > 0) this->mouse_capture_widget = widget;
811  break;
812  }
813 
814  case WID_M_SHUFFLE: // toggle shuffle
815  if (_music.IsShuffle()) {
816  _music.Unshuffle();
817  } else {
818  _music.Shuffle();
819  }
820  this->SetWidgetLoweredState(WID_M_SHUFFLE, _music.IsShuffle());
821  this->SetWidgetDirty(WID_M_SHUFFLE);
822  break;
823 
824  case WID_M_PROGRAMME: // show track selection
825  ShowMusicTrackSelection();
826  break;
827 
828  case WID_M_ALL: case WID_M_OLD: case WID_M_NEW:
829  case WID_M_EZY: case WID_M_CUSTOM1: case WID_M_CUSTOM2: // playlist
830  _music.ChangePlaylist((MusicSystem::PlaylistChoices)(widget - WID_M_ALL));
831  break;
832  }
833  }
834 };
835 
836 static const NWidgetPart _nested_music_window_widgets[] = {
838  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
839  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_MUSIC_JAZZ_JUKEBOX_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
840  NWidget(WWT_SHADEBOX, COLOUR_GREY),
841  NWidget(WWT_STICKYBOX, COLOUR_GREY),
842  EndContainer(),
843 
846  NWidget(WWT_PANEL, COLOUR_GREY, -1), SetFill(1, 1), EndContainer(),
848  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_PREV), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_SKIP_TO_PREV, STR_MUSIC_TOOLTIP_SKIP_TO_PREVIOUS_TRACK),
849  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_NEXT), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_SKIP_TO_NEXT, STR_MUSIC_TOOLTIP_SKIP_TO_NEXT_TRACK_IN_SELECTION),
850  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_STOP), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_STOP_MUSIC, STR_MUSIC_TOOLTIP_STOP_PLAYING_MUSIC),
851  NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_M_PLAY), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_PLAY_MUSIC, STR_MUSIC_TOOLTIP_START_PLAYING_MUSIC),
852  EndContainer(),
853  NWidget(WWT_PANEL, COLOUR_GREY, -1), SetFill(1, 1), EndContainer(),
854  EndContainer(),
855  NWidget(WWT_PANEL, COLOUR_GREY, WID_M_SLIDERS),
856  NWidget(NWID_HORIZONTAL), SetPIP(20, 20, 20),
858  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetFill(1, 0), SetDataTip(STR_MUSIC_MUSIC_VOLUME, STR_NULL),
859  NWidget(WWT_EMPTY, COLOUR_GREY, WID_M_MUSIC_VOL), SetMinimalSize(67, 0), SetMinimalTextLines(1, 0), SetFill(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
861  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MIN, STR_NULL),
862  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
863  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
864  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
865  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
866  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
867  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MAX, STR_NULL),
868  EndContainer(),
869  EndContainer(),
871  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetFill(1, 0), SetDataTip(STR_MUSIC_EFFECTS_VOLUME, STR_NULL),
872  NWidget(WWT_EMPTY, COLOUR_GREY, WID_M_EFFECT_VOL), SetMinimalSize(67, 0), SetMinimalTextLines(1, 0), SetFill(1, 0), SetDataTip(0x0, STR_MUSIC_TOOLTIP_DRAG_SLIDERS_TO_SET_MUSIC),
874  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MIN, STR_NULL),
875  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
876  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
877  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
878  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
879  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MARKER, STR_NULL), SetFill(1, 0),
880  NWidget(WWT_LABEL, COLOUR_GREY, -1), SetDataTip(STR_MUSIC_RULER_MAX, STR_NULL),
881  EndContainer(),
882  EndContainer(),
883  EndContainer(),
884  EndContainer(),
885  EndContainer(),
886  NWidget(WWT_PANEL, COLOUR_GREY, WID_M_BACKGROUND),
887  NWidget(NWID_HORIZONTAL), SetPIP(6, 0, 6),
889  NWidget(NWID_SPACER), SetFill(0, 1),
890  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_SHUFFLE), SetMinimalSize(50, 8), SetDataTip(STR_MUSIC_SHUFFLE, STR_MUSIC_TOOLTIP_TOGGLE_PROGRAM_SHUFFLE),
891  NWidget(NWID_SPACER), SetFill(0, 1),
892  EndContainer(),
893  NWidget(NWID_VERTICAL), SetPadding(0, 0, 3, 3),
894  NWidget(WWT_LABEL, COLOUR_GREY, WID_M_TRACK), SetFill(0, 0), SetDataTip(STR_MUSIC_TRACK, STR_NULL),
895  NWidget(WWT_PANEL, COLOUR_GREY, WID_M_TRACK_NR), EndContainer(),
896  EndContainer(),
897  NWidget(NWID_VERTICAL), SetPadding(0, 3, 3, 0),
898  NWidget(WWT_LABEL, COLOUR_GREY, WID_M_TRACK_TITLE), SetFill(1, 0), SetDataTip(STR_MUSIC_XTITLE, STR_NULL),
899  NWidget(WWT_PANEL, COLOUR_GREY, WID_M_TRACK_NAME), SetFill(1, 0), EndContainer(),
900  EndContainer(),
902  NWidget(NWID_SPACER), SetFill(0, 1),
903  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_M_PROGRAMME), SetMinimalSize(50, 8), SetDataTip(STR_MUSIC_PROGRAM, STR_MUSIC_TOOLTIP_SHOW_MUSIC_TRACK_SELECTION),
904  NWidget(NWID_SPACER), SetFill(0, 1),
905  EndContainer(),
906  EndContainer(),
907  EndContainer(),
909  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_ALL), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_ALL, STR_MUSIC_TOOLTIP_SELECT_ALL_TRACKS_PROGRAM),
910  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_OLD), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_OLD_STYLE, STR_MUSIC_TOOLTIP_SELECT_OLD_STYLE_MUSIC),
911  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_NEW), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_NEW_STYLE, STR_MUSIC_TOOLTIP_SELECT_NEW_STYLE_MUSIC),
912  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_EZY), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_EZY_STREET, STR_MUSIC_TOOLTIP_SELECT_EZY_STREET_STYLE),
913  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_CUSTOM1), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_1, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_1_USER_DEFINED),
914  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_M_CUSTOM2), SetFill(1, 0), SetDataTip(STR_MUSIC_PLAYLIST_CUSTOM_2, STR_MUSIC_TOOLTIP_SELECT_CUSTOM_2_USER_DEFINED),
915  EndContainer(),
916 };
917 
918 static WindowDesc _music_window_desc(
919  WDP_AUTO, "music", 0, 0,
921  0,
922  _nested_music_window_widgets, lengthof(_nested_music_window_widgets)
923 );
924 
925 void ShowMusicWindow()
926 {
927  AllocateWindowDescFront<MusicWindow>(&_music_window_desc, 0);
928 }
Functions related to OTTD&#39;s strings.
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:46
Metadata about a music track.
Normal push-button (no toggle button) with image caption.
Definition: widget_type.h:103
Playlist music_set
all songs in current music set, in set order
Definition: music_gui.cpp:61
void Shuffle()
Enable shuffle mode and restart playback.
Definition: music_gui.cpp:184
Types related to the music widgets.
Music window; Window numbers:
Definition: window_type.h:590
Horizontally center the text.
Definition: gfx_func.h:95
void ChangePlaylistPosition(int ofs)
Change playlist position pointer by the given offset, making sure to keep it within valid range...
Definition: music_gui.cpp:384
bool IsPlaying() const
Is the player getting music right now?
Definition: music_gui.cpp:269
Right button.
Definition: music_widget.h:18
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:110
static const uint NUM_SONGS_PLAYLIST
Maximum number of songs in the (custom) playlist.
Previous button.
Definition: music_widget.h:31
High level window description.
Definition: window_gui.h:166
Playlist active_playlist
current play order of songs, including any shuffle
Definition: music_gui.cpp:59
static int GetIndexOfUsedSet()
Get the index of the currently active graphics set.
Stop button.
Definition: music_widget.h:33
Centered label.
Definition: widget_type.h:55
bool IsShuffle() const
Is shuffle mode enabled?
Definition: music_gui.cpp:275
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:62
Horizontal container.
Definition: widget_type.h:73
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:76
Generic functions for replacing base data (graphics, sounds).
void Play()
Start/restart playback at current song.
Definition: music_gui.cpp:211
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition: music_gui.cpp:775
Music track selection; Window numbers:
Definition: window_type.h:596
bool IsCustomPlaylist() const
Is one of the custom playlists selected?
Definition: music_gui.cpp:288
static const uint NUM_SONGS_AVAILABLE
Maximum number of songs in the full playlist; theme song + the classes.
MusicSettings music
settings related to music/sound
Playlist.
Definition: music_widget.h:17
Old button.
Definition: music_widget.h:46
Close box (at top-left of a window)
Definition: widget_type.h:67
void BuildPlaylists()
Rebuild all playlists for the current music set.
Definition: music_gui.cpp:100
static NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:963
byte playlist
The playlist (number) to play.
char songname[32]
name of song displayed in UI
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Definition: music_gui.cpp:522
static bool SetSet(const char *name)
Set the set to be used.
bool playing
Whether music is playing.
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition: music_gui.cpp:555
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:24
virtual void PlaySong(const MusicSongInfo &song)=0
Play a particular song.
void Next()
Skip to next track.
Definition: music_gui.cpp:239
Functions, definitions and such used only by the GUI.
Old button.
Definition: music_widget.h:21
Sliders.
Definition: music_widget.h:35
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:175
Ezy button.
Definition: music_widget.h:23
New button.
Definition: music_widget.h:47
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:908
Pseudo random number generator.
Data structure for an opened window.
Definition: window_gui.h:276
Playlist displayed_playlist
current playlist as displayed in GUI, never in shuffled order
Definition: music_gui.cpp:60
void PlaylistAdd(size_t song_index)
Append a song to a custom playlist.
Definition: music_gui.cpp:298
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1044
void CheckStatus()
Check that music is playing if it should, and that appropriate playlist is active for game/main menu...
Definition: music_gui.cpp:257
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
Functions related to low-level strings.
Shuffle button.
Definition: music_widget.h:43
Custom2 button.
Definition: music_widget.h:50
Invisible widget that takes some space.
Definition: widget_type.h:77
All button.
Definition: music_widget.h:20
Functions related to errors.
All data of a music set.
#define FONT_HEIGHT_SMALL
Height of characters in the small (FS_SMALL) font.
Definition: gfx_func.h:173
virtual void SetVolume(byte vol)=0
Set the volume, if possible.
Effect volume.
Definition: music_widget.h:37
Track playing.
Definition: music_widget.h:39
bool shuffle
Whether to shuffle the music.
void InitializeMusic()
Prepare the music system for use.
Definition: music_gui.cpp:444
Clear button.
Definition: music_widget.h:26
void MusicLoop()
Check music playback status and start/stop/song-finished.
Definition: music_gui.cpp:424
static const uint NUM_SONGS_CLASS
Maximum number of songs in the &#39;class&#39; playlists.
const char * name
The name of the base set.
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1012
Functions related to the gfx engine.
Track name.
Definition: music_widget.h:42
void PlaylistClear()
Remove all songs from the current custom playlist.
Definition: music_gui.cpp:369
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:78
Types related to global configuration settings.
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:945
void Stop()
Stop playback and set flag that we don&#39;t intend to play music.
Definition: music_gui.cpp:230
Base for all music playback.
Definition of base types and functions in a cross-platform compatible way.
Program button.
Definition: music_widget.h:44
A number of safeguards to prevent using unsafe methods.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:102
void Prev()
Skip to previous track.
Definition: music_gui.cpp:248
Geometry functions.
byte custom_1[33]
The order of the first custom playlist.
Simple depressed panel.
Definition: widget_type.h:48
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:136
static const MusicSet * GetSet(int index)
Get the name of the graphics set at the specified index.
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1112
const char * filename
file on disk containing song (when used in MusicSet class, this pointer is owned by MD5File object fo...
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:63
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:498
Some generic types.
static MusicDriver * GetInstance()
Get the currently active instance of the music driver.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
Track number.
Definition: music_widget.h:40
Functions related to sound.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
virtual bool IsSongPlaying()=0
Are we currently playing a song?
static const uint8 PC_BLACK
Black palette colour.
Definition: gfx_func.h:203
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
Definition: music_gui.cpp:487
Custom2 button.
Definition: music_widget.h:25
Window caption.
Definition: music_widget.h:15
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Definition: music_gui.cpp:714
static const int WIDGET_LIST_END
indicate the end of widgets&#39; list for vararg functions
Definition: widget_type.h:20
void Unshuffle()
Disable shuffle and restart playback.
Definition: music_gui.cpp:200
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:38
Track title.
Definition: music_widget.h:41
PlaylistEntry GetCurrentSong() const
Return the current song, or a dummy if none.
Definition: music_gui.cpp:281
byte music_vol
The requested music volume.
byte tracknr
track number of song displayed in UI
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:59
If set the frame is lowered and the background colour brighter (ie. buttons when pressed) ...
Definition: window_gui.h:29
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:48
Custom1 button.
Definition: music_widget.h:24
New button.
Definition: music_widget.h:22
uint set_index
index of song in set
Definition: music_gui.cpp:41
void ChangeMusicSet(const char *set_name)
Change to named music set, and reset playback.
Definition: music_gui.cpp:170
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
Definition: music_gui.cpp:460
Vertical container.
Definition: widget_type.h:75
Functions for setting GUIs.
bool loop
song should play in a tight loop if possible, never ending
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:997
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
Definition: music_gui.cpp:672
Functions related to zooming.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition: music_gui.cpp:477
Music volume.
Definition: music_widget.h:36
const MusicSet * set
music set the song comes from
Definition: music_gui.cpp:40
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition: music_gui.cpp:763
Music set selection.
Definition: music_widget.h:19
Coordinates of a point in 2D.
int cat_index
entry index in CAT file, for filetype==MTT_MPSMIDI
Drop down list.
Definition: widget_type.h:68
byte custom_2[33]
The order of the second custom playlist.
void PlaylistRemove(size_t song_index)
Remove a song from a custom playlist.
Definition: music_gui.cpp:337
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
virtual void StopSong()=0
Stop playing the current song.
void ChangePlaylist(PlaylistChoices pl)
Switch to another playlist, or reload the current one.
Definition: music_gui.cpp:144
Background of the window.
Definition: music_widget.h:38
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:61
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:64
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:981
int32 WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:705
Specification of a rectangle with absolute coordinates of all edges.
Text is written right-to-left by default.
Definition: strings_type.h:24
Window functions not directly related to making/drawing windows.
Find a place automatically.
Definition: window_gui.h:154
Play button.
Definition: music_widget.h:34
Ezy button.
Definition: music_widget.h:48
void OnDropdownSelect(int widget, int index) override
A dropdown option associated to this window has been selected.
Definition: music_gui.cpp:587
Next button.
Definition: music_widget.h:32
All button.
Definition: music_widget.h:45
void SaveCustomPlaylist(PlaylistChoices pl)
Save a custom playlist to settings after modification.
Definition: music_gui.cpp:399
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:427
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:60
This file contains all sprite-related enums and defines.
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:62
byte effect_vol
The requested effects volume.
Game options window; Window numbers:
Definition: window_type.h:606
static const MusicSet * GetUsedSet()
Return the used set.
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1074
Left button.
Definition: music_widget.h:16
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3316
(Toggle) Button with text
Definition: widget_type.h:53
static void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:49
Custom1 button.
Definition: music_widget.h:49
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199
static const char * ini_set
The set as saved in the config file.