]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/menu/xonotic/soundlist.c
Safer localcmd calls
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / soundlist.c
1 #ifdef INTERFACE
2 CLASS(XonoticSoundList) EXTENDS(XonoticListBox)
3         METHOD(XonoticSoundList, configureXonoticSoundList, void(entity))
4         ATTRIB(XonoticSoundList, rowsPerItem, float, 1)
5         METHOD(XonoticSoundList, resizeNotify, void(entity, vector, vector, vector, vector))
6         METHOD(XonoticSoundList, drawListBoxItem, void(entity, float, vector, float))
7         METHOD(XonoticSoundList, getSounds, void(entity))
8         METHOD(XonoticSoundList, stopSound, void(entity))
9         METHOD(XonoticSoundList, startSound, void(entity, float))
10         METHOD(XonoticSoundList, pauseSound, void(entity))
11         METHOD(XonoticSoundList, soundName, string(entity, float))
12         METHOD(XonoticSoundList, clickListBoxItem, void(entity, float, vector))
13         METHOD(XonoticSoundList, keyDown, float(entity, float, float, float))
14         METHOD(XonoticSoundList, destroy, void(entity))
15         METHOD(XonoticSoundList, showNotify, void(entity))
16
17         ATTRIB(XonoticSoundList, listSound, float, -1)
18         ATTRIB(XonoticSoundList, realFontSize, vector, '0 0 0')
19         ATTRIB(XonoticSoundList, columnNameOrigin, float, 0)
20         ATTRIB(XonoticSoundList, columnNameSize, float, 0)
21         ATTRIB(XonoticSoundList, realUpperMargin, float, 0)
22         ATTRIB(XonoticSoundList, origin, vector, '0 0 0')
23         ATTRIB(XonoticSoundList, itemAbsSize, vector, '0 0 0')
24
25         ATTRIB(XonoticSoundList, lastClickedSound, float, -1)
26         ATTRIB(XonoticSoundList, lastClickedTime, float, 0)
27         ATTRIB(XonoticSoundList, filterString, string, string_null)
28 ENDCLASS(XonoticSoundList)
29
30 entity makeXonoticSoundList();
31 void StopSound_Click(entity btn, entity me);
32 void StartSound_Click(entity btn, entity me);
33 void PauseSound_Click(entity btn, entity me);
34 void PrevSound_Click(entity btn, entity me);
35 void NextSound_Click(entity btn, entity me);
36 void SoundList_Filter_Change(entity box, entity me);
37 void SoundList_Menu_Track_Change(entity box, entity me);
38 void SoundList_Menu_Track_Reset(entity box, entity me);
39 #endif
40
41 #ifdef IMPLEMENTATION
42
43 entity makeXonoticSoundList()
44 {
45         entity me;
46         me = spawnXonoticSoundList();
47         me.configureXonoticSoundList(me);
48         return me;
49 }
50
51 void XonoticSoundList_configureXonoticSoundList(entity me)
52 {
53         me.configureXonoticListBox(me);
54         me.getSounds(me);
55 }
56
57 string XonoticSoundList_soundName(entity me, float i )
58 {
59         string s;
60         s = search_getfilename(me.listSound, i);
61         s = substring(s, 15, strlen(s) - 15 - 4);  // sound/cdtracks/, .ogg
62         return s;
63 }
64
65
66 void XonoticSoundList_getSounds(entity me)
67 {
68         string s;
69         float i;
70
71         if(me.filterString)
72                 //subdirectory in filterString allowed
73                 s=strcat("sound/cdtracks/*", me.filterString, "*.ogg");
74         else
75                 s="sound/cdtracks/*.ogg";
76
77         if(me.listSound >= 0)
78                 search_end(me.listSound);
79
80         me.listSound = search_begin(s, FALSE, TRUE);
81
82         if(me.listSound < 0)
83                 me.nItems=0;
84         else
85                 me.nItems=search_getsize(me.listSound);
86
87         cvar_set("music_playlist_list0", "");
88         s = "";
89         for(i=0; i<me.nItems; ++i)
90         {
91                 cvar_set("music_playlist_list0", strcat(cvar_string("music_playlist_list0"), me.soundName(me,i), " "));
92         }
93 }
94
95 void XonoticSoundList_destroy(entity me)
96 {
97         search_end(me.listSound);
98 }
99
100 void XonoticSoundList_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
101 {
102         me.itemAbsSize = '0 0 0';
103         SUPER(XonoticSoundList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
104
105         me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize_y * me.itemHeight));
106         me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize_x * (1 - me.controlWidth)));
107         me.realUpperMargin = 0.5 * (1 - me.realFontSize_y);
108
109         me.columnNameOrigin = me.realFontSize_x;
110         me.columnNameSize = 1 - 2 * me.realFontSize_x;
111 }
112
113 void XonoticSoundList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
114 {
115         string s;
116         if(isSelected)
117                 draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
118
119         if(cvar("music_playlist_current0") == i)
120         {
121                 float f = cvar("music_playlist_sampleposition0");
122                 if(f == 0 || (((time * 2) & 1) && f > 0))
123                         s = ">";
124                 draw_Text(me.realUpperMargin * eY, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);
125         }
126
127         s = me.soundName(me,i);
128         if(s == cvar_defstring("menu_cdtrack"))
129                 s = strcat(s, " [default menu track]");
130         else if(s == cvar_string("menu_cdtrack"))
131                 s = strcat(s, " [current menu track]");
132         s = strcat(ftos(i+1), ") ", s);
133         s = draw_TextShortenToWidth(s, me.columnNameSize, 0, me.realFontSize);
134         draw_Text(me.realUpperMargin * eY + me.columnNameOrigin * eX, s, me.realFontSize, '1 1 1', SKINALPHA_TEXT, 0);
135 }
136
137 void XonoticSoundList_showNotify(entity me)
138 {
139         me.getSounds(me);
140 }
141
142 void SoundList_Menu_Track_Change(entity box, entity me)
143 {
144         cvar_set("menu_cdtrack", me.soundName(me,me.selectedItem));
145 }
146
147 void SoundList_Menu_Track_Reset(entity box, entity me)
148 {
149         cvar_set("menu_cdtrack", cvar_defstring("menu_cdtrack"));
150 }
151
152 void SoundList_Filter_Change(entity box, entity me)
153 {
154         if(me.filterString)
155                 strunzone(me.filterString);
156
157         if(box.text != "")
158                 me.filterString = strzone(box.text);
159         else
160                 me.filterString = string_null;
161
162         me.getSounds(me);
163 }
164
165 void XonoticSoundList_stopSound(entity me)
166 {
167         // STOP: list 0 is disabled by setting the index to 999
168         // we set sampleposition0 to -1 to indicate that music is stopped
169         cvar_set("music_playlist_index", "999");
170         localcmd("\nwait; music_playlist_sampleposition0 -1\n");
171 }
172
173 void StopSound_Click(entity btn, entity me)
174 {
175         me.stopSound(me);
176 }
177
178 void XonoticSoundList_startSound(entity me, float offset)
179 {
180         float f;
181         if(offset)
182         {
183                 f = bound(0, cvar("music_playlist_current0") + offset, me.nItems - 1);
184                 if(f == cvar("music_playlist_current0"))
185                         return;
186         }
187         else
188                 f = me.selectedItem;
189         // START: list 0 is disabled by setting the index to 999
190         // we set current0 to the selected track and sampleposition0 to 0 to forget value saved by the engine
191         // then we switch back to list 0
192         cvar_set("music_playlist_index", "999");
193         cvar_set("music_playlist_current0", ftos(f));
194         localcmd("\nwait; music_playlist_sampleposition0 0; wait; music_playlist_index 0\n");
195 }
196
197 void StartSound_Click(entity btn, entity me)
198 {
199         me.startSound(me, 0);
200 }
201
202 void PrevSound_Click(entity btn, entity me)
203 {
204         me.startSound(me, -1);
205 }
206
207 void NextSound_Click(entity btn, entity me)
208 {
209         me.startSound(me, +1);
210 }
211
212 void XonoticSoundList_pauseSound(entity me)
213 {
214         // PAUSE: list 0 is disabled by setting the index to 999
215         // (we know the track is paused because the engine sets sampleposition0 to remember current position)
216         // RESUME: list 0 is enabled by setting the index to 0
217         // (we reset sampleposition0 to 0 to mark the track as in playing back state)
218         if(cvar("music_playlist_index") == 0)
219                 localcmd("\nmusic_playlist_index 999\n");
220         else
221                 localcmd("\nmusic_playlist_index 0; wait; music_playlist_sampleposition0 0\n");
222 }
223
224 void PauseSound_Click(entity btn, entity me)
225 {
226         me.pauseSound(me);
227 }
228
229 void XonoticSoundList_clickListBoxItem(entity me, float i, vector where)
230 {
231         if(i == me.lastClickedSound)
232                 if(time < me.lastClickedTime + 0.3)
233                 {
234                         // DOUBLE CLICK!
235                         me.setSelected(me, i);
236                         me.startSound(me, 0);
237                 }
238         me.lastClickedSound = i;
239         me.lastClickedTime = time;
240 }
241
242 float XonoticSoundList_keyDown(entity me, float scan, float ascii, float shift)
243 {
244         if(scan == K_ENTER || scan == K_KP_ENTER) {
245                 me.startSound(me, 0);
246                 return 1;
247         }
248         else if(scan == K_SPACE) {
249                 me.pauseSound(me);
250                 return 1;
251         }
252         else
253                 return SUPER(XonoticSoundList).keyDown(me, scan, ascii, shift);
254 }
255 #endif
256