ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/main_beos.cpp
Revision: 1.2
Committed: 2000-10-10T21:57:21Z (23 years, 6 months ago) by cebix
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
bumped version number to 4.1

File Contents

# User Rev Content
1 cebix 1.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 cebix 1.2 "SIDPlayer\nVersion " VERSION "\n\n"
308 cebix 1.1 "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     }