ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/main_beos.cpp
Revision: 1.1
Committed: 2000-09-19T15:34:11Z (23 years, 6 months ago) by cebix
Branch: MAIN
Log Message:
can now compile as a portable command-line SDL-based application

File Contents

# Content
1 /*
2 * main_beos.cpp - SIDPlayer BeOS main program
3 *
4 * SIDPlayer (C) Copyright 1996-2000 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "sys.h"
22
23 #include <AppKit.h>
24 #include <InterfaceKit.h>
25 #include <storage/Path.h>
26 #include <media/SoundPlayer.h>
27
28 #include <stdio.h>
29
30 #include "main.h"
31 #include "prefs_window.h"
32
33
34 // Message codes
35 const uint32 MSG_NEW_MODULE = 'load';
36 const uint32 MSG_NEW_SONG = 'song';
37 const uint32 MSG_SHOW_PREFS = 'pref';
38 const uint32 MSG_PLAY_PAUSE = 'plpa';
39 const uint32 MSG_STOP = 'stop';
40 const uint32 MSG_NEXT = 'next';
41 const uint32 MSG_PREV = 'prev';
42
43
44 class MainWindow;
45 class SpeedSlider;
46
47 // Application object
48 class SIDPlayer : public BApplication {
49 public:
50 SIDPlayer();
51 virtual ~SIDPlayer();
52 virtual void ArgvReceived(int32 argc, char **argv);
53 virtual void RefsReceived(BMessage *msg);
54 virtual void MessageReceived(BMessage *msg);
55 virtual void ReadyToRun(void);
56 virtual void AboutRequested(void);
57
58 private:
59 static void buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format);
60
61 MainWindow *main_window;
62 PrefsWindow *prefs_window;
63 BSoundPlayer player;
64 bool player_stopped;
65 };
66
67
68 // Main window object
69 class MainWindow : public BWindow {
70 public:
71 MainWindow();
72 virtual bool QuitRequested(void);
73 virtual void MessageReceived(BMessage *msg);
74
75 private:
76 BStringView *make_name_display(BRect frame, char *label_text, BView *parent);
77
78 rgb_color fill_color;
79
80 BStringView *name_view;
81 BStringView *author_view;
82 BStringView *copyright_view;
83 BStringView *position_view;
84 SpeedSlider *speed_slider;
85 };
86
87
88 // Top view object (handles drag&drop)
89 class TopView : public BView {
90 public:
91 TopView(BRect frame, const char *name, uint32 resizingMode, uint32 flags);
92 virtual void MessageReceived(BMessage *msg);
93 virtual void KeyDown(const char *bytes, int32 numBytes);
94 };
95
96
97 // Buttons
98 class PlayPauseButton : public BButton {
99 public:
100 PlayPauseButton(BRect frame, BMessage *msg);
101 virtual void Draw(BRect update);
102 };
103
104 class StopButton : public BButton {
105 public:
106 StopButton(BRect frame, BMessage *msg);
107 virtual void Draw(BRect update);
108 };
109
110 class NextButton : public BButton {
111 public:
112 NextButton(BRect frame, BMessage *msg);
113 virtual void Draw(BRect update);
114 };
115
116 class PrevButton : public BButton {
117 public:
118 PrevButton(BRect frame, BMessage *msg);
119 virtual void Draw(BRect update);
120 };
121
122
123 // Speed slider
124 class SpeedSlider : public BSlider {
125 public:
126 SpeedSlider(BRect frame, const char *name) : BSlider(frame, name, "Speed", NULL, -100, 100, B_TRIANGLE_THUMB)
127 {
128 SetHashMarks(B_HASH_MARKS_TOP);
129 SetHashMarkCount(3);
130 const rgb_color bar_color = {128, 128, 216, 0};
131 SetBarColor(bar_color);
132 SetValue(0);
133 }
134 virtual ~SpeedSlider() {}
135 virtual void SetValue(int32 value)
136 {
137 int percent = value < 0 ? 100 + value / 2 : 100 + value;
138 sprintf(status, "%d%%", percent);
139 SIDAdjustSpeed(percent);
140 BSlider::SetValue(value);
141 }
142 virtual char *UpdateText(void) const
143 {
144 return status;
145 }
146
147 private:
148 mutable char status[32];
149 };
150
151
152 /*
153 * Application constructor
154 */
155
156 #if B_HOST_IS_LENDIAN
157 const media_raw_audio_format audio_format = {44100.0, 2, media_raw_audio_format::B_AUDIO_SHORT, B_MEDIA_LITTLE_ENDIAN, 4096};
158 #else
159 const media_raw_audio_format audio_format = {44100.0, 2, media_raw_audio_format::B_AUDIO_SHORT, B_MEDIA_BIG_ENDIAN, 4096};
160 #endif
161
162 SIDPlayer::SIDPlayer() : BApplication("application/x-vnd.cebix-SIDPlayer"), player(&audio_format, "SIDPlayer", buffer_proc)
163 {
164 main_window = NULL;
165 player.SetHasData(true);
166 player_stopped = true;
167 }
168
169
170 /*
171 * Application destructor
172 */
173
174 SIDPlayer::~SIDPlayer()
175 {
176 main_window = NULL;
177 prefs_window = NULL;
178 player.Stop();
179 player_stopped = true;
180 }
181
182
183 /*
184 * Shell arguments received
185 */
186
187 void SIDPlayer::ArgvReceived(int32 argc, char **argv)
188 {
189 if (argc >= 2) {
190 player.Stop();
191 LoadPSIDFile(argv[1]);
192 player.Start();
193 player_stopped = false;
194 if (main_window)
195 main_window->PostMessage(MSG_NEW_MODULE);
196 }
197 }
198
199
200 /*
201 * Tracker arguments received
202 */
203
204 void SIDPlayer::RefsReceived(BMessage *msg)
205 {
206 entry_ref the_ref;
207 if (msg->FindRef("refs", &the_ref) == B_NO_ERROR) {
208 BEntry the_entry;
209 if (the_entry.SetTo(&the_ref) == B_NO_ERROR) {
210 if (the_entry.IsFile()) {
211 BPath the_path;
212 the_entry.GetPath(&the_path);
213 player.Stop();
214 LoadPSIDFile(the_path.Path());
215 player.Start();
216 player_stopped = false;
217 if (main_window)
218 main_window->PostMessage(MSG_NEW_MODULE);
219 }
220 }
221 }
222 }
223
224
225 /*
226 * Message received
227 */
228
229 void SIDPlayer::MessageReceived(BMessage *msg)
230 {
231 switch (msg->what) {
232
233 case B_SIMPLE_DATA: // Dropped message
234 RefsReceived(msg);
235 break;
236
237 case MSG_SHOW_PREFS:
238 if (!prefs_window_open)
239 prefs_window = new PrefsWindow();
240 else if (prefs_window)
241 prefs_window->Activate(true);
242 break;
243
244 case MSG_PLAY_PAUSE:
245 if (player_stopped) {
246 player.Start();
247 player_stopped = false;
248 } else {
249 player.Stop();
250 player_stopped = true;
251 }
252 break;
253
254 case MSG_STOP:
255 player.Stop();
256 player_stopped = true;
257 SelectSong(current_song);
258 main_window->PostMessage(MSG_NEW_SONG);
259 break;
260
261 case MSG_NEXT:
262 if (current_song < number_of_songs-1) {
263 player.Stop();
264 SelectSong(current_song + 1);
265 main_window->PostMessage(MSG_NEW_SONG);
266 if (!player_stopped)
267 player.Start();
268 }
269 break;
270
271 case MSG_PREV:
272 if (current_song > 0) {
273 player.Stop();
274 SelectSong(current_song - 1);
275 main_window->PostMessage(MSG_NEW_SONG);
276 if (!player_stopped)
277 player.Start();
278 }
279 break;
280
281 default:
282 BApplication::MessageReceived(msg);
283 break;
284 }
285 }
286
287
288 /*
289 * Arguments processed, open player window
290 */
291
292 void SIDPlayer::ReadyToRun(void)
293 {
294 main_window = new MainWindow();
295 if (psid_loaded)
296 main_window->PostMessage(MSG_NEW_MODULE);
297 }
298
299
300 /*
301 * Show About window
302 */
303
304 void AboutWindow(void)
305 {
306 BAlert *theAlert = new BAlert("",
307 "SIDPlayer\nVersion 4.0\n\n"
308 "Copyright " B_UTF8_COPYRIGHT " 1996-2000 Christian Bauer\n"
309 "E-mail: Christian.Bauer@uni-mainz.de\n"
310 "http://www.uni-mainz.de/~bauec002/\n\n"
311 "SIDPlayer comes with ABSOLUTELY NO\n"
312 "WARRANTY. This is free software, and\n"
313 "you are welcome to redistribute it\n"
314 "under the terms of the GNU General\n"
315 "Public License.\n",
316 "OK", NULL, NULL, B_WIDTH_FROM_LABEL);
317
318 BTextView *theText = theAlert->TextView();
319 if (theText) {
320 theText->SetStylable(true);
321 theText->Select(0, 9);
322 BFont ourFont;
323 theText->SetFontAndColor(be_bold_font);
324 theText->GetFontAndColor(2, &ourFont, NULL);
325 ourFont.SetSize(24);
326 theText->SetFontAndColor(&ourFont);
327 }
328 theAlert->Go();
329 }
330
331 void SIDPlayer::AboutRequested(void)
332 {
333 AboutWindow();
334 }
335
336
337 /*
338 * SoundPlayer buffer procedure
339 */
340
341 void SIDPlayer::buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format)
342 {
343 SIDCalcBuffer((uint8 *)buffer, size);
344 }
345
346
347 /*
348 * Main window constructor
349 */
350
351 MainWindow::MainWindow() : BWindow(BRect(0, 0, 284, 96), "SIDPlayer", B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS)
352 {
353 fill_color = ui_color(B_PANEL_BACKGROUND_COLOR);
354 BRect b = Bounds();
355
356 // Move window to right position
357 Lock();
358 MoveTo(80, 80);
359
360 // Create menu bar
361 BMenuBar *bar = new BMenuBar(BRect(0, 0, b.right, b.bottom), "menubar");
362 BMenu *menu = new BMenu("File");
363 menu->AddItem(new BMenuItem("About SIDPlayer" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED)));
364 menu->AddItem(new BSeparatorItem());
365 menu->AddItem(new BMenuItem("Sound Control" B_UTF8_ELLIPSIS, new BMessage(MSG_SHOW_PREFS), 'P'));
366 menu->AddItem(new BSeparatorItem());
367 menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
368 menu->SetTargetForItems(be_app);
369 bar->AddItem(menu);
370 AddChild(bar);
371 SetKeyMenuBar(bar);
372 float menu_height = bar->Bounds().Height();
373
374 // Resize window to fit menu bar
375 ResizeBy(0, menu_height);
376
377 // Light gray background
378 TopView *top = new TopView(BRect(0, menu_height, b.right, b.bottom + menu_height), "main", B_FOLLOW_NONE, B_WILL_DRAW);
379 AddChild(top);
380 top->SetViewColor(fill_color);
381
382 // Name/author/copyright display
383 name_view = make_name_display(BRect(0, 5, 279, 21), "Name", top);
384 author_view = make_name_display(BRect(0, 25, 279, 41), "Author", top);
385 copyright_view = make_name_display(BRect(0, 45, 279, 61), "Copyright", top);
386
387 // Buttons
388 top->AddChild(new PlayPauseButton(BRect(6, 67, 36, 91), new BMessage(MSG_PLAY_PAUSE)));
389 top->AddChild(new StopButton(BRect(37, 67, 67, 91), new BMessage(MSG_STOP)));
390 top->AddChild(new PrevButton(BRect(68, 67, 98, 91), new BMessage(MSG_PREV)));
391 top->AddChild(new NextButton(BRect(99, 67, 129, 91), new BMessage(MSG_NEXT)));
392
393 // Position indicator
394 top->AddChild(position_view = new BStringView(BRect(134, 72, 193, 85), "position", ""));
395 position_view->SetViewColor(fill_color);
396
397 // Speed slider
398 top->AddChild(speed_slider = new SpeedSlider(BRect(194, 62, 279, 63), "speed"));
399
400 // Show window
401 top->MakeFocus();
402 Unlock();
403 Show();
404 }
405
406
407 /*
408 * Create name display field
409 */
410
411 BStringView *MainWindow::make_name_display(BRect frame, char *label_text, BView *parent)
412 {
413 // Label to the left of the display field
414 BRect label_rect = frame;
415 label_rect.right = label_rect.left + 65;
416
417 BStringView *label = new BStringView(label_rect, "", label_text);
418 parent->AddChild(label);
419 label->SetViewColor(fill_color);
420 label->SetLowColor(fill_color);
421 label->SetAlignment(B_ALIGN_RIGHT);
422 label->SetFont(be_bold_font);
423
424 // Box around display field
425 BRect frame_rect = frame;
426 frame_rect.left += 70;
427
428 BBox *box = new BBox(frame_rect);
429 parent->AddChild(box);
430 box->SetViewColor(fill_color);
431 box->SetLowColor(fill_color);
432
433 // The display field
434 BRect textview_rect = frame_rect;
435 textview_rect.OffsetTo(0, 0);
436 textview_rect.InsetBy(4, 2);
437
438 BStringView *text = new BStringView(textview_rect, "", "");
439 box->AddChild(text);
440 text->SetViewColor(fill_color);
441 text->SetLowColor(fill_color);
442 text->SetFont(be_plain_font);
443 return text;
444 }
445
446
447 /*
448 * Main window closed, quit program
449 */
450
451 bool MainWindow::QuitRequested(void)
452 {
453 be_app->PostMessage(B_QUIT_REQUESTED);
454 return true;
455 }
456
457
458 /*
459 * Message received
460 */
461
462 void MainWindow::MessageReceived(BMessage *msg)
463 {
464 switch (msg->what) {
465 case MSG_NEW_MODULE:
466 // Update text views
467 Lock();
468 name_view->SetText(module_name);
469 author_view->SetText(author_name);
470 copyright_view->SetText(copyright_info);
471 Unlock();
472 // falls through
473
474 case MSG_NEW_SONG:
475 // Update position indicator and speed slider
476 if (number_of_songs > 0) {
477 char str[16];
478 sprintf(str, "Song %d/%d", current_song + 1, number_of_songs);
479 position_view->SetText(str);
480 }
481 speed_slider->SetValue(0);
482 break;
483
484 case MSG_SHOW_PREFS:
485 case MSG_PLAY_PAUSE:
486 case MSG_STOP:
487 case MSG_NEXT:
488 case MSG_PREV:
489 be_app->PostMessage(msg);
490 break;
491
492 default:
493 BWindow::MessageReceived(msg);
494 break;
495 }
496 }
497
498
499 /*
500 * TopView handles dropped messages (load new PSID module) and keypresses
501 */
502
503 TopView::TopView(BRect frame, const char *name, uint32 resizingMode, uint32 flags)
504 : BView(frame, name, resizingMode, flags) {}
505
506 void TopView::MessageReceived(BMessage *msg)
507 {
508 if (msg->what == B_SIMPLE_DATA)
509 be_app->PostMessage(msg);
510 else
511 BView::MessageReceived(msg);
512 }
513
514 void TopView::KeyDown(const char *bytes, int32 numBytes)
515 {
516 BMessage *msg = Window()->CurrentMessage();
517 uint32 modifiers = 0;
518 msg->FindInt32("modifiers", (int32 *)&modifiers);
519
520 switch (bytes[0]) {
521 case 'p':
522 case 'P':
523 Window()->PostMessage(MSG_PLAY_PAUSE);
524 break;
525
526 case B_ESCAPE:
527 case B_SPACE:
528 case 's':
529 case 'S':
530 Window()->PostMessage(MSG_STOP);
531 break;
532
533 case B_LEFT_ARROW:
534 Window()->PostMessage(MSG_PREV);
535 break;
536
537 case B_RIGHT_ARROW:
538 case 'n':
539 case 'N':
540 Window()->PostMessage(MSG_NEXT);
541 break;
542
543 case 'q':
544 case 'Q':
545 be_app->PostMessage(B_QUIT_REQUESTED);
546 break;
547 }
548 }
549
550
551 /*
552 * Play/Pause button
553 */
554
555 PlayPauseButton::PlayPauseButton(BRect frame, BMessage *msg) : BButton(frame, "play", "", msg) {};
556
557 void PlayPauseButton::Draw(BRect update)
558 {
559 // First draw normal button
560 BButton::Draw(update);
561
562 // Then draw play/pause image on top of it
563 if (Value())
564 SetHighColor(255, 255, 255);
565 else
566 SetHighColor(0, 0, 0);
567
568 FillRect(BRect(11, 8, 13, 16));
569 FillTriangle(BPoint(16, 8), BPoint(16, 16), BPoint(20, 12));
570 }
571
572
573 /*
574 * Stop button
575 */
576
577 StopButton::StopButton(BRect frame, BMessage *msg) : BButton(frame, "stop", "", msg) {};
578
579 void StopButton::Draw(BRect update)
580 {
581 // First draw normal button
582 BButton::Draw(update);
583
584 // Then draw stop image on top of it
585 if (Value())
586 SetHighColor(255, 255, 255);
587 else
588 SetHighColor(0, 0, 0);
589
590 FillRect(BRect(11, 8, 20, 16));
591 }
592
593
594 /*
595 * "Next" button
596 */
597
598 NextButton::NextButton(BRect frame, BMessage *msg) : BButton(frame, "next", "", msg) {};
599
600 void NextButton::Draw(BRect update)
601 {
602 // First draw normal button
603 BButton::Draw(update);
604
605 // Then draw "next" image on top of it
606 if (Value())
607 SetHighColor(255, 255, 255);
608 else
609 SetHighColor(0, 0, 0);
610
611 FillTriangle(BPoint(12, 8), BPoint(12, 16), BPoint(16, 12));
612 FillRect(BRect(17, 8, 19, 16));
613 }
614
615
616 /*
617 * "Prev" button
618 */
619
620 PrevButton::PrevButton(BRect frame, BMessage *msg) : BButton(frame, "prev", "", msg) {};
621
622 void PrevButton::Draw(BRect update)
623 {
624 // First draw normal button
625 BButton::Draw(update);
626
627 // Then draw "prev" image on top of it
628 if (Value())
629 SetHighColor(255, 255, 255);
630 else
631 SetHighColor(0, 0, 0);
632
633 FillRect(BRect(12, 8, 14, 16));
634 FillTriangle(BPoint(19, 8), BPoint(19, 16), BPoint(15, 12));
635 }
636
637
638 /*
639 * Main program
640 */
641
642 int main(int argc, char **argv)
643 {
644 InitAll();
645 SIDPlayer *the_app = new SIDPlayer();
646 the_app->Run();
647 delete the_app;
648 ExitAll();
649 return 0;
650 }