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