(svn r3281) -Feature: [OSX] added native cocoa sound and video drivers (egladil)
you can still use SDL drivers if you like and you have to run "make upgradeconf" to start using the cocoa drivers (or manually write WITH_COCOA:=1)
since SDL breaks the cocoa drivers, you can't compile with both SDL and cocoa support
Using cocoa drivers makes it easier to make universal binaries and it solves:
-FS#18 [OSX] SDL is weird in universal binaries
-FS#2 [OSX] lazy pointer crash on exit
-FS#10 [OSX] linking error when linking statically to SDL 1.2.8 (needless to explain this, but it means it should be able to compile statically with the default settings now)
-[ 1215073 ] Switching to large size out of fullscreen crashes
Using SDL drivers will still have those issues though
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "table/strings.h"
#include "functions.h"
#include "window.h"
#include "gui.h"
#include "gfx.h"
#include "sound.h"
#include "hal.h"
#include "macros.h"
#include "variables.h"
static byte _music_wnd_cursong;
static bool _song_is_active;
static byte _cur_playlist[33];
#define NUM_SONGS_AVAILABLE 22
static byte _playlist_all[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0
};
static byte _playlist_old_style[] = {
1, 8, 2, 9, 14, 15, 19, 13, 0
};
static byte _playlist_new_style[] = {
6, 11, 10, 17, 21, 18, 5, 0
};
static byte _playlist_ezy_street[] = {
12, 7, 16, 3, 20, 4, 0
};
static byte * const _playlists[] = {
_playlist_all,
_playlist_old_style,
_playlist_new_style,
_playlist_ezy_street,
msf.custom_1,
msf.custom_2,
};
// Map the order of the song names to the numbers of the midi filenames
static const byte midi_idx[] = {
0, // Tycoon DELUXE Theme
2, // Easy Driver
3, // Little Red Diesel
17, // Cruise Control
7, // Don't Walk!
9, // Fell Apart On Me
4, // City Groove
19, // Funk Central
6, // Stoke It
12, // Road Hog
5, // Aliens Ate My Railway
1, // Snarl Up
18, // Stroll On
10, // Can't Get There From Here
8, // Sawyer's Tune
13, // Hold That Train!
21, // Movin' On
15, // Goss Groove
16, // Small Town
14, // Broomer's Oil Rag
20, // Jammit
11 // Hard Drivin'
};
static void SkipToPrevSong(void)
{
byte *b = _cur_playlist;
byte *p = b;
byte t;
// empty playlist
if (b[0] == 0) return;
// find the end
do p++; while (p[0] != 0);
// and copy the bytes
t = *--p;
while (p != b) {
p--;
p[1] = p[0];
}
*b = t;
_song_is_active = false;
}
static void SkipToNextSong(void)
{
byte* b = _cur_playlist;
byte t;
t = b[0];
if (t != 0) {
while (b[1] != 0) {
b[0] = b[1];
b++;
}
b[0] = t;
}
_song_is_active = false;
}
static void MusicVolumeChanged(byte new_vol)
{
_music_driver->set_volume(new_vol);
}
static void DoPlaySong(void)
{
char filename[256];
snprintf(filename, sizeof(filename), "%sgm_tt%.2d.gm",
_path.gm_dir, midi_idx[_music_wnd_cursong - 1]);
_music_driver->play_song(filename);
}
static void DoStopMusic(void)
{
_music_driver->stop_song();
}
static void SelectSongToPlay(void)
{
uint i = 0;
memset(_cur_playlist, 0, sizeof(_cur_playlist));
do {
_cur_playlist[i] = _playlists[msf.playlist][i];
} while (_playlists[msf.playlist][i++] != 0 && i < lengthof(_cur_playlist) - 1);
if (msf.shuffle) {
i = 500;
do {
uint32 r = InteractiveRandom();
byte *a = &_cur_playlist[GB(r, 0, 5)];
byte *b = &_cur_playlist[GB(r, 8, 5)];
if (*a != 0 && *b != 0) {
byte t = *a;
*a = *b;
*b = t;
}
} while (--i);
}
}
static void StopMusic(void)
{
_music_wnd_cursong = 0;
DoStopMusic();
_song_is_active = false;
InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
}
static void PlayPlaylistSong(void)
{
if (_cur_playlist[0] == 0) {
SelectSongToPlay();
if (_cur_playlist[0] == 0) return;
}
_music_wnd_cursong = _cur_playlist[0];
DoPlaySong();
_song_is_active = true;
InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 9);
}
void ResetMusic(void)
{
_music_wnd_cursong = 1;
DoPlaySong();
}
void MusicLoop(void)
{
if (!msf.btn_down && _song_is_active) {
StopMusic();
} else if (msf.btn_down && !_song_is_active) {
PlayPlaylistSong();
}
if (_song_is_active == false) return;
if (!_music_driver->is_song_playing()) {
if (_game_mode != GM_MENU) {
StopMusic();
SkipToNextSong();
PlayPlaylistSong();
} else {
ResetMusic();
}
}
}
static void MusicTrackSelectionWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT: {
const byte* p;
uint i;
int y;
w->disabled_state = (msf.playlist <= 3) ? (1 << 11) : 0;
w->click_state |= 0x18;
DrawWindowWidgets(w);
GfxFillRect(3, 23, 3+177,23+191,0);
GfxFillRect(251, 23, 251+177,23+191,0);
DrawStringCentered(92, 15, STR_01EE_TRACK_INDEX, 0);
SetDParam(0, STR_01D5_ALL + msf.playlist);
DrawStringCentered(340, 15, STR_01EF_PROGRAM, 0);
for (i = 1; i <= NUM_SONGS_AVAILABLE; i++) {
SetDParam(0, i);
SetDParam(2, i);
SetDParam(1, SPECSTR_SONGNAME);
DrawString(4, 23+(i-1)*6, (i < 10) ? STR_01EC_0 : STR_01ED, 0);
}
for (i = 0; i != 6; i++) {
DrawStringCentered(216, 45 + i * 8, STR_01D5_ALL + i, (i == msf.playlist) ? 0xC : 0x10);
}
DrawStringCentered(216, 45+8*6+16, STR_01F0_CLEAR, 0);
DrawStringCentered(216, 45+8*6+16*2, STR_01F1_SAVE, 0);
y = 23;
for (p = _playlists[msf.playlist], i = 0; (i = *p) != 0; p++) {
SetDParam(0, i);
SetDParam(1, SPECSTR_SONGNAME);
SetDParam(2, i);
DrawString(252, y, (i < 10) ? STR_01EC_0 : STR_01ED, 0);
y += 6;
}
break;
}
case WE_CLICK:
switch (e->click.widget) {
case 3: { /* add to playlist */
int y = (e->click.pt.y - 23) / 6;
uint i;
byte *p;
if (msf.playlist < 4) return;
if (!IS_INT_INSIDE(y, 0, NUM_SONGS_AVAILABLE)) return;
p = _playlists[msf.playlist];
for (i = 0; i != 32; i++) {
if (p[i] == 0) {
p[i] = y + 1;
p[i + 1] = 0;
SetWindowDirty(w);
SelectSongToPlay();
break;
}
}
} break;
case 11: /* clear */
_playlists[msf.playlist][0] = 0;
SetWindowDirty(w);
StopMusic();
SelectSongToPlay();
break;
case 12: /* save */
ShowInfo("MusicTrackSelectionWndProc:save not implemented\n");
break;
case 5: case 6: case 7: case 8: case 9: case 10: /* set playlist */
msf.playlist = e->click.widget - 5;
SetWindowDirty(w);
InvalidateWindow(WC_MUSIC_WINDOW, 0);
StopMusic();
SelectSongToPlay();
break;
}
break;
}
}
static const Widget _music_track_selection_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5,STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 431, 0, 13, STR_01EB_MUSIC_PROGRAM_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 431, 14, 217, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 2, 181, 22, 215, 0x0, STR_01FA_CLICK_ON_MUSIC_TRACK_TO},
{ WWT_IMGBTN, RESIZE_NONE, 14, 250, 429, 22, 215, 0x0, STR_01F2_CURRENT_PROGRAM_OF_MUSIC},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 44, 51, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 52, 59, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 60, 67, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 68, 75, 0x0, STR_0330_SELECT_EZY_STREET_STYLE},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 76, 83, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 84, 91, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 108, 115, 0x0, STR_01F8_CLEAR_CURRENT_PROGRAM_CUSTOM1},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 186, 245, 124, 131, 0x0, STR_01F9_SAVE_MUSIC_SETTINGS},
{ WIDGETS_END},
};
static const WindowDesc _music_track_selection_desc = {
104, 131, 432, 218,
WC_MUSIC_TRACK_SELECTION,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_music_track_selection_widgets,
MusicTrackSelectionWndProc
};
static void ShowMusicTrackSelection(void)
{
AllocateWindowDescFront(&_music_track_selection_desc, 0);
}
static void MusicWindowWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT: {
uint i;
StringID str;
w->click_state |= 0x280;
DrawWindowWidgets(w);
GfxFillRect(187, 16, 200, 33, 0);
for (i = 0; i != 8; i++) {
int color = 0xD0;
if (i > 4) {
color = 0xBF;
if (i > 6) {
color = 0xB8;
}
}
GfxFillRect(187, 33 - i * 2, 200, 33 - i * 2, color);
}
GfxFillRect(60, 46, 239, 52, 0);
if (_song_is_active == 0 || _music_wnd_cursong == 0) {
str = STR_01E3;
} else {
SetDParam(0, _music_wnd_cursong);
str = (_music_wnd_cursong < 10) ? STR_01E4_0 : STR_01E5;
}
DrawString(62, 46, str, 0);
str = STR_01E6;
if (_song_is_active != 0 && _music_wnd_cursong != 0) {
str = STR_01E7;
SetDParam(0, SPECSTR_SONGNAME);
SetDParam(1, _music_wnd_cursong);
}
DrawStringCentered(155, 46, str, 0);
DrawString(60, 38, STR_01E8_TRACK_XTITLE, 0);
for (i = 0; i != 6; i++) {
DrawStringCentered(25 + i * 50, 59, STR_01D5_ALL + i, msf.playlist == i ? 0xC : 0x10);
}
DrawStringCentered(31, 43, STR_01E9_SHUFFLE, (msf.shuffle ? 0xC : 0x10));
DrawStringCentered(269, 43, STR_01EA_PROGRAM, 0);
DrawStringCentered(141, 15, STR_01DB_MUSIC_VOLUME, 0);
DrawStringCentered(141, 29, STR_01DD_MIN_MAX, 0);
DrawStringCentered(247, 15, STR_01DC_EFFECTS_VOLUME, 0);
DrawStringCentered(247, 29, STR_01DD_MIN_MAX, 0);
DrawFrameRect(108, 23, 174, 26, 14, FR_LOWERED);
DrawFrameRect(214, 23, 280, 26, 14, FR_LOWERED);
DrawFrameRect(108 + (msf.music_vol>>1),
22,
111 + (msf.music_vol>>1),
28,
14,
0);
DrawFrameRect(214 + (msf.effect_vol>>1),
22,
217 + (msf.effect_vol>>1),
28,
14,
0);
} break;
case WE_CLICK:
switch(e->click.widget) {
case 2: // skip to prev
if (!_song_is_active)
return;
SkipToPrevSong();
break;
case 3: // skip to next
if (!_song_is_active)
return;
SkipToNextSong();
break;
case 4: // stop playing
msf.btn_down = false;
break;
case 5: // start playing
msf.btn_down = true;
break;
case 6:{ // volume sliders
byte *vol,new_vol;
int x = e->click.pt.x - 88;
if (x < 0)
return;
vol = &msf.music_vol;
if (x >= 106) {
vol = &msf.effect_vol;
x -= 106;
}
new_vol = min(max(x-21,0)*2,127);
if (new_vol != *vol) {
*vol = new_vol;
if (vol == &msf.music_vol)
MusicVolumeChanged(new_vol);
SetWindowDirty(w);
}
_left_button_clicked = false;
} break;
case 10: //toggle shuffle
msf.shuffle ^= 1;
StopMusic();
SelectSongToPlay();
break;
case 11: //show track selection
ShowMusicTrackSelection();
break;
case 12: case 13: case 14: case 15: case 16: case 17: // playlist
msf.playlist = e->click.widget - 12;
SetWindowDirty(w);
InvalidateWindow(WC_MUSIC_TRACK_SELECTION, 0);
StopMusic();
SelectSongToPlay();
break;
}
break;
case WE_MOUSELOOP:
InvalidateWindowWidget(WC_MUSIC_WINDOW, 0, 7);
break;
}
}
static const Widget _music_window_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 299, 0, 13, STR_01D2_JAZZ_JUKEBOX, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 0, 21, 14, 35, 0x2C5, STR_01DE_SKIP_TO_PREVIOUS_TRACK},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 22, 43, 14, 35, 0x2C6, STR_01DF_SKIP_TO_NEXT_TRACK_IN_SELECTION},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 44, 65, 14, 35, 0x2C7, STR_01E0_STOP_PLAYING_MUSIC},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 66, 87, 14, 35, 0x2C8, STR_01E1_START_PLAYING_MUSIC},
{ WWT_IMGBTN, RESIZE_NONE, 14, 88, 299, 14, 35, 0x0, STR_01E2_DRAG_SLIDERS_TO_SET_MUSIC},
{ WWT_IMGBTN, RESIZE_NONE, 14, 186, 201, 15, 34, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 0, 299, 36, 57, 0x0, STR_NULL},
{ WWT_IMGBTN, RESIZE_NONE, 14, 59, 240, 45, 53, 0x0, STR_NULL},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 6, 55, 42, 49, 0x0, STR_01FB_TOGGLE_PROGRAM_SHUFFLE},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 244, 293, 42, 49, 0x0, STR_01FC_SHOW_MUSIC_TRACK_SELECTION},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 0, 49, 58, 65, 0x0, STR_01F3_SELECT_ALL_TRACKS_PROGRAM},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 50, 99, 58, 65, 0x0, STR_01F4_SELECT_OLD_STYLE_MUSIC},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 100, 149, 58, 65, 0x0, STR_01F5_SELECT_NEW_STYLE_MUSIC},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 150, 199, 58, 65, 0x0, STR_0330_SELECT_EZY_STREET_STYLE},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 200, 249, 58, 65, 0x0, STR_01F6_SELECT_CUSTOM_1_USER_DEFINED},
{ WWT_PUSHIMGBTN, RESIZE_NONE, 14, 250, 299, 58, 65, 0x0, STR_01F7_SELECT_CUSTOM_2_USER_DEFINED},
{ WIDGETS_END},
};
static const WindowDesc _music_window_desc = {
0, 22, 300, 66,
WC_MUSIC_WINDOW,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_music_window_widgets,
MusicWindowWndProc
};
void ShowMusicWindow(void)
{
AllocateWindowDescFront(&_music_window_desc, 0);
}