repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / midiplayer / ScopeView.cpp
blob6044ec356576b5c04b4f6e77f190efe357aa890f
1 /*
2 * Copyright (c) 2004 Matthijs Hollemans
3 * Copyright (c) 2008-2014 Haiku, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 #include "ScopeView.h"
27 #include <Catalog.h>
28 #include <Locale.h>
29 #include <Synth.h>
30 #include <Window.h>
33 #undef B_TRANSLATION_CONTEXT
34 #define B_TRANSLATION_CONTEXT "Scope View"
37 // #pragma mark - ScopeView
40 ScopeView::ScopeView()
42 BView(BRect(0, 0, 180, 63), NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP,
43 B_WILL_DRAW),
44 fIsPlaying(false),
45 fIsEnabled(true),
46 fHaveFile(false),
47 fIsLoading(false),
48 fIsLiveInput(false),
49 fSampleCount(Bounds().IntegerWidth()),
50 fLeftSamples(new int16[fSampleCount]),
51 fRightSamples(new int16[fSampleCount]),
52 fScopeThreadID(-1)
57 ScopeView::~ScopeView()
59 delete[] fLeftSamples;
60 delete[] fRightSamples;
64 void ScopeView::AttachedToWindow()
66 SetViewColor(0, 0, 0);
68 fIsFinished = false;
69 fScopeThreadID = spawn_thread(_Thread, "ScopeThread",
70 B_NORMAL_PRIORITY, this);
71 if (fScopeThreadID > 0)
72 resume_thread(fScopeThreadID);
76 void
77 ScopeView::DetachedFromWindow()
79 if (fScopeThreadID > 0) {
80 fIsFinished = true;
81 status_t exitValue;
82 wait_for_thread(fScopeThreadID, &exitValue);
87 void
88 ScopeView::Draw(BRect updateRect)
90 super::Draw(updateRect);
92 if (fIsLoading)
93 DrawLoading();
94 else if (!fHaveFile && !fIsLiveInput)
95 DrawNoFile();
96 else if (!fIsEnabled)
97 DrawDisabled();
98 else if (fIsPlaying || fIsLiveInput)
99 DrawPlaying();
100 else
101 DrawStopped();
105 int32
106 ScopeView::_Thread(void* data)
108 return ((ScopeView*) data)->Thread();
112 int32
113 ScopeView::Thread()
115 // Because Pulse() was too slow, I created a thread that tells the
116 // ScopeView to repaint itself. Note that we need to call LockLooper
117 // with a timeout, otherwise we'll deadlock in DetachedFromWindow().
119 while (!fIsFinished) {
120 if (fIsEnabled && (fIsPlaying || fIsLiveInput)) {
121 if (LockLooperWithTimeout(50000) == B_OK) {
122 Invalidate();
123 UnlockLooper();
126 snooze(50000);
129 return 0;
133 void
134 ScopeView::DrawLoading()
136 DrawText(B_TRANSLATE("Loading instruments" B_UTF8_ELLIPSIS));
140 void
141 ScopeView::DrawNoFile()
143 DrawText(B_TRANSLATE("Drop MIDI file here"));
147 void
148 ScopeView::DrawDisabled()
150 SetHighColor(64, 64, 64);
152 StrokeLine(BPoint(0, Bounds().Height() / 2),
153 BPoint(Bounds().Width(), Bounds().Height() / 2));
157 void
158 ScopeView::DrawStopped()
160 SetHighColor(0, 130, 0);
162 StrokeLine(BPoint(0, Bounds().Height() / 2),
163 BPoint(Bounds().Width(), Bounds().Height() / 2));
167 void
168 ScopeView::DrawPlaying()
170 int32 width = (int32) Bounds().Width();
171 int32 height = (int32) Bounds().Height();
173 // Scope drawing magic based on code by Michael Pfeiffer.
175 int32 size = be_synth->GetAudio(fLeftSamples, fRightSamples, fSampleCount);
176 if (size > 0) {
177 SetHighColor(255, 0, 130);
178 SetLowColor(0, 130, 0);
180 int32 x;
181 int32 y;
182 int32 sx = 0;
183 int32 f = (height << 16) / 65535;
184 int32 dy = height / 2 + 1;
185 for (int32 i = 0; i < width; i++) {
186 x = sx / width;
187 y = ((fLeftSamples[x] * f) >> 16) + dy;
188 FillRect(BRect(i, y, i, y));
190 y = ((fRightSamples[x] * f) >> 16) + dy;
191 FillRect(BRect(i, y, i, y), B_SOLID_LOW);
193 sx += size;
199 void
200 ScopeView::DrawText(const char* text)
202 font_height height;
203 GetFontHeight(&height);
205 float stringWidth = StringWidth(text);
206 float stringHeight = height.ascent + height.descent;
208 float x = (Bounds().Width() - stringWidth) / 2;
209 float y = height.ascent + (Bounds().Height() - stringHeight) / 2;
211 SetHighColor(255, 255, 255);
212 SetLowColor(ViewColor());
213 SetDrawingMode(B_OP_OVER);
215 DrawString(text, BPoint(x, y));