* Restructured the sources a bit, renamed SliderView to VolumeControl,
VolumeSlider to VolumeWindow. * The VolumeControl is now a replicant, and be be dragged to the Tracker. * Hence, moved all volume control stuff from VolumeWindow into the VolumeControl class directly. * Changed menu a bit. Note that controlling the physical output currently does not work, but that's a problem of the media node in question (probably the multi audio add-on, I'll have a look). * Added a small delay when clicking on the slider directly before the window is hidden, so that you'll get some feedback of your action. * Added --add-volume, and --volume-control options to "desklink", the former adds the volume control icon to the deskbar, the latter opens the volume control window directly. * Further cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30031 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,11 +2,15 @@ SubDir HAIKU_TOP src bin desklink ;
|
|||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
|
UsePrivateHeaders app ;
|
||||||
|
|
||||||
BinCommand desklink :
|
BinCommand desklink :
|
||||||
desklink.cpp
|
desklink.cpp
|
||||||
VolumeSlider.cpp
|
|
||||||
DeskButton.cpp
|
DeskButton.cpp
|
||||||
|
MediaReplicant.cpp
|
||||||
MixerControl.cpp
|
MixerControl.cpp
|
||||||
|
VolumeControl.cpp
|
||||||
|
VolumeWindow.cpp
|
||||||
|
|
||||||
: be libmedia.so
|
: be libmedia.so
|
||||||
: desklink.rdef
|
: desklink.rdef
|
||||||
|
|||||||
@@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2009, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval
|
||||||
|
* François Revol
|
||||||
|
* Marcus Overhagen
|
||||||
|
* Jonas Sundström
|
||||||
|
* Axel Dörfler, [email protected].
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! Volume control, and media shortcuts in Deskbar
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Alert.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <MenuItem.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <PopUpMenu.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "desklink.h"
|
||||||
|
#include "iconfile.h"
|
||||||
|
#include "MixerControl.h"
|
||||||
|
#include "VolumeWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kMsgOpenMediaSettings = 'mese';
|
||||||
|
static const uint32 kMsgOpenSoundSettings = 'sose';
|
||||||
|
static const uint32 kMsgOpenMediaPlayer = 'omep';
|
||||||
|
static const uint32 kMsgToggleBeep = 'tdbp';
|
||||||
|
static const uint32 kMsgVolumeWhich = 'svwh';
|
||||||
|
|
||||||
|
static const char* kReplicantName = "MediaReplicant";
|
||||||
|
// R5 name needed, Media prefs manel removes by name
|
||||||
|
|
||||||
|
static const char* kSettingsFile = "x-vnd.Haiku-desklink";
|
||||||
|
|
||||||
|
|
||||||
|
class MediaReplicant : public BView {
|
||||||
|
public:
|
||||||
|
MediaReplicant(BRect frame, const char* name,
|
||||||
|
uint32 resizeMask = B_FOLLOW_ALL,
|
||||||
|
uint32 flags = B_WILL_DRAW | B_NAVIGABLE);
|
||||||
|
MediaReplicant(BMessage* archive);
|
||||||
|
|
||||||
|
virtual ~MediaReplicant();
|
||||||
|
|
||||||
|
// archiving overrides
|
||||||
|
static MediaReplicant* Instantiate(BMessage* data);
|
||||||
|
virtual status_t Archive(BMessage* data, bool deep = true) const;
|
||||||
|
|
||||||
|
// BView overrides
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void MouseDown(BPoint point);
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _LaunchByPath(const char* path);
|
||||||
|
status_t _LaunchBySignature(const char* signature);
|
||||||
|
void _Launch(const char* prettyName,
|
||||||
|
const char* signature, directory_which base,
|
||||||
|
const char* fileName);
|
||||||
|
void _LoadSettings();
|
||||||
|
void _SaveSettings();
|
||||||
|
void _Init();
|
||||||
|
|
||||||
|
BBitmap* fIcon;
|
||||||
|
VolumeWindow* fVolumeSlider;
|
||||||
|
bool fDontBeep;
|
||||||
|
// don't beep on volume change
|
||||||
|
int32 fVolumeWhich;
|
||||||
|
// which volume parameter to act on (Mixer/Phys.Output)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MediaReplicant::MediaReplicant(BRect frame, const char* name,
|
||||||
|
uint32 resizeMask, uint32 flags)
|
||||||
|
: BView(frame, name, resizeMask, flags),
|
||||||
|
fVolumeSlider(NULL)
|
||||||
|
{
|
||||||
|
_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MediaReplicant::MediaReplicant(BMessage* message)
|
||||||
|
: BView(message),
|
||||||
|
fVolumeSlider(NULL)
|
||||||
|
{
|
||||||
|
_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MediaReplicant::~MediaReplicant()
|
||||||
|
{
|
||||||
|
delete fIcon;
|
||||||
|
_SaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MediaReplicant*
|
||||||
|
MediaReplicant::Instantiate(BMessage* data)
|
||||||
|
{
|
||||||
|
if (!validate_instantiation(data, kReplicantName))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return new(std::nothrow) MediaReplicant(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MediaReplicant::Archive(BMessage* data, bool deep) const
|
||||||
|
{
|
||||||
|
status_t status = BView::Archive(data, deep);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return data->AddString("add_on", kAppSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BView *parent = Parent();
|
||||||
|
if (parent)
|
||||||
|
SetViewColor(parent->ViewColor());
|
||||||
|
|
||||||
|
BView::AttachedToWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::Draw(BRect rect)
|
||||||
|
{
|
||||||
|
BView::Draw(rect);
|
||||||
|
|
||||||
|
SetDrawingMode(B_OP_OVER);
|
||||||
|
DrawBitmap(fIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::MouseDown(BPoint point)
|
||||||
|
{
|
||||||
|
int32 buttons = B_PRIMARY_MOUSE_BUTTON;
|
||||||
|
if (Looper() != NULL && Looper()->CurrentMessage() != NULL)
|
||||||
|
Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
|
||||||
|
|
||||||
|
BPoint where = ConvertToScreen(point);
|
||||||
|
|
||||||
|
if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
|
||||||
|
BPopUpMenu* menu = new BPopUpMenu("", false, false);
|
||||||
|
menu->SetFont(be_plain_font);
|
||||||
|
|
||||||
|
menu->AddItem(new BMenuItem("Media Preferences" B_UTF8_ELLIPSIS,
|
||||||
|
new BMessage(kMsgOpenMediaSettings)));
|
||||||
|
menu->AddItem(new BMenuItem("Sound Preferences" B_UTF8_ELLIPSIS,
|
||||||
|
new BMessage(kMsgOpenSoundSettings)));
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
|
menu->AddItem(new BMenuItem("Open MediaPlayer",
|
||||||
|
new BMessage(kMsgOpenMediaPlayer)));
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
|
BMenu* subMenu = new BMenu("Options");
|
||||||
|
menu->AddItem(subMenu);
|
||||||
|
|
||||||
|
BMenuItem* item = new BMenuItem("Control Physical Output",
|
||||||
|
new BMessage(kMsgVolumeWhich));
|
||||||
|
item->SetMarked(fVolumeWhich == VOLUME_USE_PHYS_OUTPUT);
|
||||||
|
subMenu->AddItem(item);
|
||||||
|
|
||||||
|
item = new BMenuItem("Beep", new BMessage(kMsgToggleBeep));
|
||||||
|
item->SetMarked(!fDontBeep);
|
||||||
|
subMenu->AddItem(item);
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
|
menu->AddItem(new BMenuItem("About" B_UTF8_ELLIPSIS,
|
||||||
|
new BMessage(B_ABOUT_REQUESTED)));
|
||||||
|
|
||||||
|
menu->SetTargetForItems(this);
|
||||||
|
subMenu->SetTargetForItems(this);
|
||||||
|
|
||||||
|
menu->Go(where, true, true, BRect(where - BPoint(4, 4),
|
||||||
|
where + BPoint(4, 4)));
|
||||||
|
} else {
|
||||||
|
// Show VolumeWindow
|
||||||
|
fVolumeSlider = new VolumeWindow(BRect(where.x, where.y,
|
||||||
|
where.x + 207, where.y + 19), fDontBeep, fVolumeWhich);
|
||||||
|
fVolumeSlider->Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::MessageReceived(BMessage *message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case B_ABOUT_REQUESTED:
|
||||||
|
(new BAlert("About Volume Control", "Volume Control\n"
|
||||||
|
" Brought to you by Jérôme DUVAL.\n\n"
|
||||||
|
"Copyright " B_UTF8_COPYRIGHT "2003-2009, Haiku",
|
||||||
|
"OK"))->Go(NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgOpenMediaPlayer:
|
||||||
|
_Launch("MediaPlayer", "application/x-vnd.Haiku-MediaPlayer",
|
||||||
|
B_SYSTEM_APPS_DIRECTORY, "MediaPlayer");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgOpenMediaSettings:
|
||||||
|
_Launch("Media Preferences", "application/x-vnd.Haiku-Media",
|
||||||
|
B_SYSTEM_PREFERENCES_DIRECTORY, "Media");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgOpenSoundSettings:
|
||||||
|
_Launch("Sounds Preferences", "application/x-vnd.Haiku-Sounds",
|
||||||
|
B_SYSTEM_PREFERENCES_DIRECTORY, "Sounds");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgToggleBeep:
|
||||||
|
{
|
||||||
|
BMenuItem* item;
|
||||||
|
if (message->FindPointer("source", (void**)&item) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item->SetMarked(!item->IsMarked());
|
||||||
|
fDontBeep = !item->IsMarked();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMsgVolumeWhich:
|
||||||
|
{
|
||||||
|
BMenuItem* item;
|
||||||
|
if (message->FindPointer("source", (void**)&item) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item->SetMarked(!item->IsMarked());
|
||||||
|
fVolumeWhich = item->IsMarked()
|
||||||
|
? VOLUME_USE_PHYS_OUTPUT : VOLUME_USE_MIXER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_MOUSE_WHEEL_CHANGED:
|
||||||
|
{
|
||||||
|
float deltaY;
|
||||||
|
if (message->FindFloat("be:wheel_delta_y", &deltaY) == B_OK
|
||||||
|
&& deltaY != 0.0) {
|
||||||
|
MixerControl mixerControl(fVolumeWhich);
|
||||||
|
mixerControl.ChangeVolumeBy(deltaY < 0 ? 6 : -6);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
BView::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MediaReplicant::_LaunchByPath(const char* path)
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
status_t status = get_ref_for_path(path, &ref);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = be_roster->Launch(&ref);
|
||||||
|
if (status != B_ALREADY_RUNNING)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// The application runs already, bring it to front
|
||||||
|
|
||||||
|
app_info appInfo;
|
||||||
|
status = be_roster->GetAppInfo(&ref, &appInfo);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return be_roster->ActivateApp(appInfo.team);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MediaReplicant::_LaunchBySignature(const char* signature)
|
||||||
|
{
|
||||||
|
status_t status = be_roster->Launch(signature);
|
||||||
|
if (status != B_ALREADY_RUNNING)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// The application runs already, bring it to front
|
||||||
|
|
||||||
|
app_info appInfo;
|
||||||
|
status = be_roster->GetAppInfo(signature, &appInfo);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return be_roster->ActivateApp(appInfo.team);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::_Launch(const char* prettyName, const char* signature,
|
||||||
|
directory_which base, const char* fileName)
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
status_t status = find_directory(base, &path);
|
||||||
|
if (status == B_OK)
|
||||||
|
path.Append(fileName);
|
||||||
|
|
||||||
|
// launch the application
|
||||||
|
if (_LaunchBySignature(signature) != B_OK
|
||||||
|
&& _LaunchByPath(path.Path()) != B_OK) {
|
||||||
|
BString message = "Couldn't launch ";
|
||||||
|
message << prettyName;
|
||||||
|
|
||||||
|
(new BAlert("desklink", message.String(), "OK"))->Go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::_LoadSettings()
|
||||||
|
{
|
||||||
|
fDontBeep = false;
|
||||||
|
fVolumeWhich = VOLUME_USE_MIXER;
|
||||||
|
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, false) < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
path.Append(kSettingsFile);
|
||||||
|
|
||||||
|
BFile settings(path.Path(), B_READ_ONLY);
|
||||||
|
if (settings.InitCheck() < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BMessage msg;
|
||||||
|
if (msg.Unflatten(&settings) < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
msg.FindInt32("volwhich", &fVolumeWhich);
|
||||||
|
msg.FindBool("dontbeep", &fDontBeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::_SaveSettings()
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, false) < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
path.Append(kSettingsFile);
|
||||||
|
|
||||||
|
BFile settings(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
|
||||||
|
if (settings.InitCheck() < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BMessage msg('CNFG');
|
||||||
|
msg.AddInt32("volwhich", fVolumeWhich);
|
||||||
|
msg.AddBool("dontbeep", fDontBeep);
|
||||||
|
|
||||||
|
ssize_t size = 0;
|
||||||
|
msg.Flatten(&settings, &size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaReplicant::_Init()
|
||||||
|
{
|
||||||
|
fIcon = new BBitmap(BRect(0, 0, kSpeakerWidth - 1, kSpeakerHeight - 1),
|
||||||
|
B_CMAP8);
|
||||||
|
fIcon->SetBits(kSpeakerBits, kSpeakerWidth*kSpeakerHeight, 0, B_CMAP8);
|
||||||
|
|
||||||
|
_LoadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" BView*
|
||||||
|
instantiate_deskbar_item(void)
|
||||||
|
{
|
||||||
|
return new MediaReplicant(BRect(0, 0, 16, 16), kReplicantName);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
* Authors:
|
* Authors:
|
||||||
* Jérôme Duval
|
* Jérôme Duval
|
||||||
* François Revol
|
* François Revol
|
||||||
|
* Axel Dörfler, [email protected].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
MixerControl::MixerControl(int32 volumeWhich, float* _value,
|
MixerControl::MixerControl(int32 volumeWhich, float* _value,
|
||||||
const char** _error)
|
const char** _error)
|
||||||
:
|
:
|
||||||
|
fVolumeWhich(volumeWhich),
|
||||||
fAudioMixerNode(NULL),
|
fAudioMixerNode(NULL),
|
||||||
fParameterWeb(NULL),
|
fParameterWeb(NULL),
|
||||||
fMixerParameter(NULL),
|
fMixerParameter(NULL),
|
||||||
@@ -170,35 +172,15 @@ MixerControl::~MixerControl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
int32
|
||||||
MixerControl::SetVolume(float volume)
|
MixerControl::VolumeWhich() const
|
||||||
{
|
{
|
||||||
if (fMixerParameter == NULL)
|
return fVolumeWhich;
|
||||||
return;
|
|
||||||
|
|
||||||
if (volume < fMin)
|
|
||||||
volume = fMin;
|
|
||||||
else if (volume > fMax)
|
|
||||||
volume = fMax;
|
|
||||||
|
|
||||||
if (volume != _GetVolume())
|
|
||||||
fMixerParameter->SetValue(&volume, sizeof(float), system_time());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MixerControl::ChangeVolumeBy(float value)
|
|
||||||
{
|
|
||||||
if (fMixerParameter == NULL || value == 0.0f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
float volume = _GetVolume();
|
|
||||||
SetVolume(volume + value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float
|
float
|
||||||
MixerControl::_GetVolume()
|
MixerControl::Volume() const
|
||||||
{
|
{
|
||||||
if (fMixerParameter == NULL)
|
if (fMixerParameter == NULL)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
@@ -210,3 +192,31 @@ MixerControl::_GetVolume()
|
|||||||
|
|
||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MixerControl::SetVolume(float volume)
|
||||||
|
{
|
||||||
|
if (fMixerParameter == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (volume < fMin)
|
||||||
|
volume = fMin;
|
||||||
|
else if (volume > fMax)
|
||||||
|
volume = fMax;
|
||||||
|
|
||||||
|
if (volume != Volume())
|
||||||
|
fMixerParameter->SetValue(&volume, sizeof(float), system_time());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MixerControl::ChangeVolumeBy(float value)
|
||||||
|
{
|
||||||
|
if (fMixerParameter == NULL || value == 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
float volume = Volume();
|
||||||
|
SetVolume(volume + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,14 @@ class BContinuousParameter;
|
|||||||
|
|
||||||
class MixerControl {
|
class MixerControl {
|
||||||
public:
|
public:
|
||||||
MixerControl(int32 volumeWhich, float *value = NULL,
|
MixerControl(int32 volumeWhich,
|
||||||
const char **error = NULL);
|
float* _value = NULL,
|
||||||
|
const char** _error = NULL);
|
||||||
~MixerControl();
|
~MixerControl();
|
||||||
|
|
||||||
|
int32 VolumeWhich() const;
|
||||||
|
float Volume() const;
|
||||||
|
|
||||||
void SetVolume(float volume);
|
void SetVolume(float volume);
|
||||||
void ChangeVolumeBy(float value);
|
void ChangeVolumeBy(float value);
|
||||||
|
|
||||||
@@ -34,13 +38,13 @@ public:
|
|||||||
float Maximum() const { return fMax; }
|
float Maximum() const { return fMax; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float _GetVolume();
|
int32 fVolumeWhich;
|
||||||
void _SetVolume(float volume);
|
|
||||||
|
|
||||||
media_node* fAudioMixerNode;
|
media_node* fAudioMixerNode;
|
||||||
BParameterWeb* fParameterWeb;
|
BParameterWeb* fParameterWeb;
|
||||||
BContinuousParameter* fMixerParameter;
|
BContinuousParameter* fMixerParameter;
|
||||||
float fMin, fMax, fStep;
|
float fMin;
|
||||||
|
float fMax;
|
||||||
|
float fStep;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MIXER_CONTROL_H
|
#endif // MIXER_CONTROL_H
|
||||||
|
|||||||
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2009, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval
|
||||||
|
* François Revol
|
||||||
|
* Axel Dörfler, [email protected].
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "VolumeControl.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Beep.h>
|
||||||
|
#include <ControlLook.h>
|
||||||
|
#include <Dragger.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
|
||||||
|
#include <AppMisc.h>
|
||||||
|
|
||||||
|
#include "desklink.h"
|
||||||
|
#include "MixerControl.h"
|
||||||
|
#include "VolumeWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
VolumeControl::VolumeControl(int32 volumeWhich, bool beep, BMessage* message)
|
||||||
|
: BSlider("VolumeControl", "Volume", message, 0, 1, B_HORIZONTAL),
|
||||||
|
fBeep(beep)
|
||||||
|
{
|
||||||
|
font_height fontHeight;
|
||||||
|
GetFontHeight(&fontHeight);
|
||||||
|
SetBarThickness(ceilf((fontHeight.ascent + fontHeight.descent) * 0.7));
|
||||||
|
|
||||||
|
_InitVolume(volumeWhich);
|
||||||
|
|
||||||
|
BRect rect(Bounds());
|
||||||
|
rect.top = rect.bottom - 7;
|
||||||
|
rect.left = rect.right - 7;
|
||||||
|
BDragger* dragger = new BDragger(rect, this,
|
||||||
|
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
||||||
|
AddChild(dragger);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VolumeControl::VolumeControl(BMessage* archive)
|
||||||
|
: BSlider(archive)
|
||||||
|
{
|
||||||
|
if (archive->FindBool("beep", &fBeep) != B_OK)
|
||||||
|
fBeep = false;
|
||||||
|
|
||||||
|
int32 volumeWhich;
|
||||||
|
if (archive->FindInt32("volume which", &volumeWhich) != B_OK)
|
||||||
|
volumeWhich = VOLUME_USE_MIXER;
|
||||||
|
|
||||||
|
_InitVolume(volumeWhich);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VolumeControl::~VolumeControl()
|
||||||
|
{
|
||||||
|
delete fMixerControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VolumeControl::Archive(BMessage* into, bool deep) const
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
status = BView::Archive(into, deep);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = into->AddString("add_on", kAppSignature);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = into->AddBool("beep", fBeep);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return into->AddInt32("volume which", fMixerControl->VolumeWhich());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VolumeControl*
|
||||||
|
VolumeControl::Instantiate(BMessage* archive)
|
||||||
|
{
|
||||||
|
if (!validate_instantiation(archive, "VolumeControl"))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return new VolumeControl(archive);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VolumeControl::AttachedToWindow()
|
||||||
|
{
|
||||||
|
BSlider::AttachedToWindow();
|
||||||
|
|
||||||
|
SetEventMask(_IsReplicant() ? 0 : B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VolumeControl::MouseDown(BPoint where)
|
||||||
|
{
|
||||||
|
// Ignore clicks on the dragger
|
||||||
|
int32 viewToken;
|
||||||
|
if (Bounds().Contains(where) && Looper()->CurrentMessage() != NULL
|
||||||
|
&& Looper()->CurrentMessage()->FindInt32("_view_token",
|
||||||
|
&viewToken) == B_OK
|
||||||
|
&& viewToken != _get_object_token_(this))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: investigate why this does not work as expected (the dragger
|
||||||
|
// frame seems to be off)
|
||||||
|
#if 0
|
||||||
|
if (BView* dragger = ChildAt(0)) {
|
||||||
|
if (!dragger->IsHidden() && dragger->Frame().Contains(where))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!IsEnabled() || !Bounds().Contains(where)) {
|
||||||
|
Invoke();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BSlider::MouseDown(where);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VolumeControl::MessageReceived(BMessage* msg)
|
||||||
|
{
|
||||||
|
switch (msg->what) {
|
||||||
|
case B_MOUSE_WHEEL_CHANGED:
|
||||||
|
{
|
||||||
|
if (Value() == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Even though the volume bar is horizontal, we use the more common
|
||||||
|
// vertical mouse wheel change
|
||||||
|
float deltaY = 0.0f;
|
||||||
|
|
||||||
|
msg->FindFloat("be:wheel_delta_y", &deltaY);
|
||||||
|
|
||||||
|
if (deltaY == 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 currentValue = Value();
|
||||||
|
int32 newValue = currentValue - int32(deltaY) * 3;
|
||||||
|
|
||||||
|
if (newValue != currentValue) {
|
||||||
|
SetValue(newValue);
|
||||||
|
if (ModificationMessage() != NULL)
|
||||||
|
Messenger().SendMessage(ModificationMessage());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BView::MessageReceived(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
VolumeControl::Invoke(BMessage* message = NULL)
|
||||||
|
{
|
||||||
|
if (fBeep && fOriginalValue != Value() && message == NULL) {
|
||||||
|
beep();
|
||||||
|
fOriginalValue = Value();
|
||||||
|
}
|
||||||
|
|
||||||
|
fMixerControl->SetVolume(Value());
|
||||||
|
|
||||||
|
return BSlider::Invoke(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VolumeControl::DrawBar()
|
||||||
|
{
|
||||||
|
BRect frame = BarFrame();
|
||||||
|
BView* view = OffscreenView();
|
||||||
|
|
||||||
|
if (be_control_look != NULL) {
|
||||||
|
uint32 flags = be_control_look->Flags(this);
|
||||||
|
rgb_color base = LowColor();
|
||||||
|
rgb_color rightFillColor = (rgb_color){255, 109, 38, 255};
|
||||||
|
rgb_color leftFillColor = (rgb_color){116, 224, 0, 255};
|
||||||
|
|
||||||
|
int32 min, max;
|
||||||
|
GetLimits(&min, &max);
|
||||||
|
float position = 1.0f * (max - min - max) / (max - min);
|
||||||
|
|
||||||
|
be_control_look->DrawSliderBar(view, frame, frame, base, leftFillColor,
|
||||||
|
rightFillColor, position, flags, Orientation());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BSlider::DrawBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
VolumeControl::UpdateText() const
|
||||||
|
{
|
||||||
|
if (!IsEnabled())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
snprintf(fText, sizeof(fText), "%ld dB", Value());
|
||||||
|
return fText;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VolumeControl::_InitVolume(int32 volumeWhich)
|
||||||
|
{
|
||||||
|
const char* errorString = NULL;
|
||||||
|
float volume = 0.0;
|
||||||
|
fMixerControl = new MixerControl(volumeWhich, &volume, &errorString);
|
||||||
|
|
||||||
|
if (errorString != NULL) {
|
||||||
|
SetLabel(errorString);
|
||||||
|
SetLimits(-60, 18);
|
||||||
|
} else {
|
||||||
|
SetLabel("Volume");
|
||||||
|
SetLimits((int32)floorf(fMixerControl->Minimum()),
|
||||||
|
(int32)ceilf(fMixerControl->Maximum()));
|
||||||
|
}
|
||||||
|
|
||||||
|
SetEnabled(errorString == NULL);
|
||||||
|
|
||||||
|
fOriginalValue = (int32)volume;
|
||||||
|
SetValue((int32)volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
VolumeControl::_IsReplicant() const
|
||||||
|
{
|
||||||
|
return dynamic_cast<VolumeWindow*>(Window()) == NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2009, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval
|
||||||
|
* François Revol
|
||||||
|
* Axel Dörfler, [email protected].
|
||||||
|
*/
|
||||||
|
#ifndef VOLUME_SLIDER_H
|
||||||
|
#define VOLUME_SLIDER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Slider.h>
|
||||||
|
|
||||||
|
class MixerControl;
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeControl : public BSlider {
|
||||||
|
public:
|
||||||
|
VolumeControl(int32 volumeWhich, bool beep,
|
||||||
|
BMessage* message);
|
||||||
|
VolumeControl(BMessage* archive);
|
||||||
|
virtual ~VolumeControl();
|
||||||
|
|
||||||
|
static VolumeControl* Instantiate(BMessage* archive);
|
||||||
|
virtual status_t Archive(BMessage* archive, bool deep = true) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
virtual void MouseDown(BPoint where);
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual status_t Invoke(BMessage* message = NULL);
|
||||||
|
|
||||||
|
virtual void DrawBar();
|
||||||
|
virtual const char* UpdateText() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InitVolume(int32 volumeWhich);
|
||||||
|
bool _IsReplicant() const;
|
||||||
|
|
||||||
|
mutable char fText[64];
|
||||||
|
MixerControl* fMixerControl;
|
||||||
|
int32 fOriginalValue;
|
||||||
|
bool fBeep;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VOLUME_SLIDER_H
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2003-2009, Haiku, Inc.
|
|
||||||
* Distributed under the terms of the MIT license.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Jérôme Duval
|
|
||||||
* François Revol
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "VolumeSlider.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <Beep.h>
|
|
||||||
#include <Box.h>
|
|
||||||
#include <ControlLook.h>
|
|
||||||
#include <Debug.h>
|
|
||||||
#include <GroupLayout.h>
|
|
||||||
#include <Screen.h>
|
|
||||||
#include <Slider.h>
|
|
||||||
|
|
||||||
#include "MixerControl.h"
|
|
||||||
|
|
||||||
#define VOLUME_CHANGED 'vlcg'
|
|
||||||
#define VOLUME_UPDATED 'vlud'
|
|
||||||
|
|
||||||
|
|
||||||
class SliderView : public BSlider {
|
|
||||||
public:
|
|
||||||
SliderView(const char* name, const char* label,
|
|
||||||
BMessage *message, int32 minValue,
|
|
||||||
int32 maxValue);
|
|
||||||
virtual ~SliderView();
|
|
||||||
|
|
||||||
virtual void MouseDown(BPoint where);
|
|
||||||
virtual void MessageReceived(BMessage* msg);
|
|
||||||
virtual void DrawBar();
|
|
||||||
virtual const char* UpdateText() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable char fText[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SliderView::SliderView(const char* name, const char* label, BMessage *message,
|
|
||||||
int32 minValue, int32 maxValue)
|
|
||||||
: BSlider("slider", label, message, minValue, maxValue, B_HORIZONTAL)
|
|
||||||
{
|
|
||||||
font_height fontHeight;
|
|
||||||
GetFontHeight(&fontHeight);
|
|
||||||
SetBarThickness(ceilf((fontHeight.ascent + fontHeight.descent) * 0.7));
|
|
||||||
|
|
||||||
SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SliderView::~SliderView()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SliderView::MouseDown(BPoint where)
|
|
||||||
{
|
|
||||||
if (!IsEnabled() || !Bounds().Contains(where))
|
|
||||||
Invoke();
|
|
||||||
|
|
||||||
BSlider::MouseDown(where);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SliderView::MessageReceived(BMessage* msg)
|
|
||||||
{
|
|
||||||
switch (msg->what) {
|
|
||||||
case B_MOUSE_WHEEL_CHANGED:
|
|
||||||
{
|
|
||||||
if (Value() == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Even though the volume bar is horizontal, we use the more common
|
|
||||||
// vertical mouse wheel change
|
|
||||||
float deltaY = 0.0f;
|
|
||||||
|
|
||||||
msg->FindFloat("be:wheel_delta_y", &deltaY);
|
|
||||||
|
|
||||||
if (deltaY == 0.0f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int32 currentValue = Value();
|
|
||||||
// deltaY is generally 1 or -1, so this should increase or decrease
|
|
||||||
// the 0-100 volume value by 5 each time. Also -5 is used because
|
|
||||||
// mousewheel up is negative but should increase the volume.
|
|
||||||
int32 newValue = MAX(MIN(currentValue + static_cast<int32>(deltaY * -5.0), 100), 0);
|
|
||||||
|
|
||||||
if (newValue != currentValue) {
|
|
||||||
SetValue(newValue);
|
|
||||||
Draw(Bounds());
|
|
||||||
Flush();
|
|
||||||
|
|
||||||
if (Window())
|
|
||||||
Window()->PostMessage(VOLUME_UPDATED);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return BView::MessageReceived(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SliderView::DrawBar()
|
|
||||||
{
|
|
||||||
BRect frame = BarFrame();
|
|
||||||
BView* view = OffscreenView();
|
|
||||||
|
|
||||||
if (be_control_look != NULL) {
|
|
||||||
uint32 flags = be_control_look->Flags(this);
|
|
||||||
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
|
|
||||||
rgb_color rightFillColor = (rgb_color){255, 109, 38, 255};
|
|
||||||
rgb_color leftFillColor = (rgb_color){116, 224, 0, 255};
|
|
||||||
|
|
||||||
int32 min, max;
|
|
||||||
GetLimits(&min, &max);
|
|
||||||
float position = 1.0f * (max - min - max) / (max - min);
|
|
||||||
|
|
||||||
be_control_look->DrawSliderBar(view, frame, frame, base, leftFillColor,
|
|
||||||
rightFillColor, position, flags, Orientation());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BSlider::DrawBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
|
||||||
SliderView::UpdateText() const
|
|
||||||
{
|
|
||||||
snprintf(fText, sizeof(fText), "%ld dB", Value());
|
|
||||||
return fText;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
VolumeSlider::VolumeSlider(BRect frame, bool dontBeep, int32 volumeWhich)
|
|
||||||
: BWindow(frame, "VolumeSlider", B_BORDERED_WINDOW_LOOK,
|
|
||||||
B_FLOATING_ALL_WINDOW_FEEL,
|
|
||||||
B_ASYNCHRONOUS_CONTROLS | B_WILL_ACCEPT_FIRST_CLICK, 0)
|
|
||||||
{
|
|
||||||
fDontBeep = dontBeep;
|
|
||||||
|
|
||||||
const char *errorString = NULL;
|
|
||||||
float value = 0.0;
|
|
||||||
fMixerControl = new MixerControl(volumeWhich, &value, &errorString);
|
|
||||||
|
|
||||||
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
|
||||||
|
|
||||||
BGroupLayout* layout = new BGroupLayout(B_HORIZONTAL);
|
|
||||||
layout->SetInsets(10, 0, 10, 0);
|
|
||||||
|
|
||||||
BBox* box = new BBox("sliderbox");
|
|
||||||
box->SetLayout(layout);
|
|
||||||
box->SetBorder(B_PLAIN_BORDER);
|
|
||||||
AddChild(box);
|
|
||||||
|
|
||||||
fHasChanged = false;
|
|
||||||
// make sure we don't beep if we don't change anything
|
|
||||||
|
|
||||||
fSlider = new SliderView("volume", errorString ? errorString : "Volume",
|
|
||||||
new BMessage(VOLUME_CHANGED), fMixerControl->Minimum(),
|
|
||||||
fMixerControl->Maximum());
|
|
||||||
fSlider->SetValue((int32)value);
|
|
||||||
fSlider->SetModificationMessage(new BMessage(VOLUME_UPDATED));
|
|
||||||
if (errorString != NULL)
|
|
||||||
fSlider->SetEnabled(false);
|
|
||||||
box->AddChild(fSlider);
|
|
||||||
|
|
||||||
fSlider->SetTarget(this);
|
|
||||||
SetPulseRate(100);
|
|
||||||
ResizeTo(300, 50);
|
|
||||||
|
|
||||||
// Make sure it's not outside the screen.
|
|
||||||
const int32 kMargin = 3;
|
|
||||||
BRect windowRect = Frame();
|
|
||||||
BRect screenFrame(BScreen(B_MAIN_SCREEN_ID).Frame());
|
|
||||||
if (screenFrame.right < windowRect.right + kMargin)
|
|
||||||
MoveBy(- kMargin - windowRect.right + screenFrame.right, 0);
|
|
||||||
if (screenFrame.bottom < windowRect.bottom + kMargin)
|
|
||||||
MoveBy(0, - kMargin - windowRect.bottom + screenFrame.bottom);
|
|
||||||
if (screenFrame.left > windowRect.left - kMargin)
|
|
||||||
MoveBy(kMargin + screenFrame.left - windowRect.left, 0);
|
|
||||||
if (screenFrame.top > windowRect.top - kMargin)
|
|
||||||
MoveBy(0, kMargin + screenFrame.top - windowRect.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VolumeSlider::~VolumeSlider()
|
|
||||||
{
|
|
||||||
delete fMixerControl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
VolumeSlider::MessageReceived(BMessage *msg)
|
|
||||||
{
|
|
||||||
switch (msg->what) {
|
|
||||||
case VOLUME_UPDATED:
|
|
||||||
puts("updated");
|
|
||||||
PRINT(("VOLUME_UPDATED\n"));
|
|
||||||
fMixerControl->SetVolume(fSlider->Value());
|
|
||||||
fHasChanged = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VOLUME_CHANGED:
|
|
||||||
puts("changed");
|
|
||||||
if (fHasChanged) {
|
|
||||||
PRINT(("VOLUME_CHANGED\n"));
|
|
||||||
fMixerControl->SetVolume(fSlider->Value());
|
|
||||||
if (!fDontBeep)
|
|
||||||
beep();
|
|
||||||
}
|
|
||||||
Quit();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
BWindow::MessageReceived(msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2003-2009, Haiku, Inc.
|
|
||||||
* Distributed under the terms of the MIT license.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Jérôme Duval
|
|
||||||
* François Revol
|
|
||||||
*/
|
|
||||||
#ifndef VOLUME_SLIDER_H
|
|
||||||
#define VOLUME_SLIDER_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <Window.h>
|
|
||||||
|
|
||||||
|
|
||||||
class BSlider;
|
|
||||||
class MixerControl;
|
|
||||||
|
|
||||||
class VolumeSlider : public BWindow {
|
|
||||||
public:
|
|
||||||
VolumeSlider(BRect frame, bool dontBeep = false,
|
|
||||||
int32 volumeWhich = 0);
|
|
||||||
~VolumeSlider();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void MessageReceived(BMessage* message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
MixerControl* fMixerControl;
|
|
||||||
bool fHasChanged;
|
|
||||||
bool fDontBeep;
|
|
||||||
BSlider* fSlider;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // VOLUME_SLIDER_H
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2009, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval
|
||||||
|
* François Revol
|
||||||
|
* Axel Dörfler, [email protected].
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "VolumeWindow.h"
|
||||||
|
|
||||||
|
#include <Box.h>
|
||||||
|
#include <GroupLayout.h>
|
||||||
|
#include <MessageRunner.h>
|
||||||
|
#include <Screen.h>
|
||||||
|
|
||||||
|
#include "VolumeControl.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32 kMsgVolumeUpdate = 'vlup';
|
||||||
|
static const uint32 kMsgVolumeChanged = 'vlcg';
|
||||||
|
|
||||||
|
|
||||||
|
VolumeWindow::VolumeWindow(BRect frame, bool dontBeep, int32 volumeWhich)
|
||||||
|
: BWindow(frame, "VolumeWindow", B_BORDERED_WINDOW_LOOK,
|
||||||
|
B_FLOATING_ALL_WINDOW_FEEL,
|
||||||
|
B_ASYNCHRONOUS_CONTROLS | B_WILL_ACCEPT_FIRST_CLICK
|
||||||
|
| B_AUTO_UPDATE_SIZE_LIMITS, 0),
|
||||||
|
fUpdatedCount(0)
|
||||||
|
{
|
||||||
|
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||||
|
|
||||||
|
BGroupLayout* layout = new BGroupLayout(B_HORIZONTAL);
|
||||||
|
layout->SetInsets(5, 5, 5, 5);
|
||||||
|
|
||||||
|
BBox* box = new BBox("sliderbox");
|
||||||
|
box->SetLayout(layout);
|
||||||
|
box->SetBorder(B_PLAIN_BORDER);
|
||||||
|
AddChild(box);
|
||||||
|
|
||||||
|
BSlider* slider = new VolumeControl(volumeWhich, !dontBeep,
|
||||||
|
new BMessage(kMsgVolumeChanged));
|
||||||
|
slider->SetModificationMessage(new BMessage(kMsgVolumeUpdate));
|
||||||
|
box->AddChild(slider);
|
||||||
|
|
||||||
|
slider->SetTarget(this);
|
||||||
|
ResizeTo(300, 50);
|
||||||
|
|
||||||
|
// Make sure it's not outside the screen.
|
||||||
|
const int32 kMargin = 3;
|
||||||
|
BRect windowRect = Frame();
|
||||||
|
BRect screenFrame(BScreen(B_MAIN_SCREEN_ID).Frame());
|
||||||
|
if (screenFrame.right < windowRect.right + kMargin)
|
||||||
|
MoveBy(- kMargin - windowRect.right + screenFrame.right, 0);
|
||||||
|
if (screenFrame.bottom < windowRect.bottom + kMargin)
|
||||||
|
MoveBy(0, - kMargin - windowRect.bottom + screenFrame.bottom);
|
||||||
|
if (screenFrame.left > windowRect.left - kMargin)
|
||||||
|
MoveBy(kMargin + screenFrame.left - windowRect.left, 0);
|
||||||
|
if (screenFrame.top > windowRect.top - kMargin)
|
||||||
|
MoveBy(0, kMargin + screenFrame.top - windowRect.top);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VolumeWindow::~VolumeWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
void
|
||||||
|
VolumeWindow::MessageReceived(BMessage *msg)
|
||||||
|
{
|
||||||
|
switch (msg->what) {
|
||||||
|
case kMsgVolumeUpdate:
|
||||||
|
fUpdatedCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMsgVolumeChanged:
|
||||||
|
if (fUpdatedCount < 2) {
|
||||||
|
// If the slider was set by click only, wait a bit until
|
||||||
|
// closing the window to give some feedback that how volume
|
||||||
|
// was changed, and that it is.
|
||||||
|
BMessage quit(B_QUIT_REQUESTED);
|
||||||
|
BMessageRunner::StartSending(this, &quit, 150000, 1);
|
||||||
|
} else
|
||||||
|
Quit();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BWindow::MessageReceived(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2009, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval
|
||||||
|
* François Revol
|
||||||
|
* Axel Dörfler, [email protected].
|
||||||
|
*/
|
||||||
|
#ifndef VOLUME_WINDOW_H
|
||||||
|
#define VOLUME_WINDOW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include "MixerControl.h"
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeWindow : public BWindow {
|
||||||
|
public:
|
||||||
|
VolumeWindow(BRect frame, bool dontBeep = false,
|
||||||
|
int32 volumeWhich = VOLUME_USE_MIXER);
|
||||||
|
virtual ~VolumeWindow();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 fUpdatedCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VOLUME_WINDOW_H
|
||||||
+21
-414
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008, Haiku. All rights reserved.
|
* Copyright 2003-2009, Haiku. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -11,424 +11,27 @@
|
|||||||
|
|
||||||
//! VolumeControl and link items in Deskbar
|
//! VolumeControl and link items in Deskbar
|
||||||
|
|
||||||
|
#include "desklink.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <strings.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <Bitmap.h>
|
|
||||||
#include <Debug.h>
|
|
||||||
#include <Deskbar.h>
|
#include <Deskbar.h>
|
||||||
#include <Dragger.h>
|
|
||||||
#include <File.h>
|
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <List.h>
|
|
||||||
#include <MenuItem.h>
|
|
||||||
#include <Message.h>
|
|
||||||
#include <MimeType.h>
|
#include <MimeType.h>
|
||||||
#include <Path.h>
|
|
||||||
#include <PopUpMenu.h>
|
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <View.h>
|
|
||||||
|
|
||||||
#include "DeskButton.h"
|
#include "DeskButton.h"
|
||||||
#include "iconfile.h"
|
#include "VolumeWindow.h"
|
||||||
#include "MixerControl.h"
|
|
||||||
#include "VolumeSlider.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define MEDIA_SETTINGS 'mese'
|
|
||||||
#define SOUND_SETTINGS 'sose'
|
|
||||||
#define OPEN_MEDIA_PLAYER 'omep'
|
|
||||||
#define TOGGLE_DONT_BEEP 'tdbp'
|
|
||||||
#define SET_VOLUME_WHICH 'svwh'
|
|
||||||
|
|
||||||
#define VOLUME_CTL_NAME "MediaReplicant"
|
|
||||||
// R5 name needed, Media prefs manel removes by name
|
|
||||||
|
|
||||||
#define SETTINGS_FILE "x-vnd.Haiku-desklink"
|
|
||||||
|
|
||||||
const char *kAppSignature = "application/x-vnd.Haiku-desklink";
|
const char *kAppSignature = "application/x-vnd.Haiku-desklink";
|
||||||
// the application signature used by the replicant to find the
|
// the application signature used by the replicant to find the
|
||||||
// supporting code
|
// supporting code
|
||||||
|
|
||||||
|
|
||||||
class _EXPORT MediaReplicant;
|
|
||||||
// the dragger part has to be exported
|
|
||||||
|
|
||||||
class MediaReplicant : public BView {
|
|
||||||
public:
|
|
||||||
MediaReplicant(BRect frame, const char *name,
|
|
||||||
uint32 resizeMask = B_FOLLOW_ALL,
|
|
||||||
uint32 flags = B_WILL_DRAW | B_NAVIGABLE);
|
|
||||||
MediaReplicant(BMessage *);
|
|
||||||
// BMessage * based constructor needed to support archiving
|
|
||||||
virtual ~MediaReplicant();
|
|
||||||
|
|
||||||
// archiving overrides
|
|
||||||
static MediaReplicant *Instantiate(BMessage *data);
|
|
||||||
virtual status_t Archive(BMessage *data, bool deep = true) const;
|
|
||||||
|
|
||||||
// misc BView overrides
|
|
||||||
virtual void AttachedToWindow();
|
|
||||||
virtual void MouseDown(BPoint);
|
|
||||||
virtual void MouseUp(BPoint);
|
|
||||||
virtual void Draw(BRect updateRect);
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void _AlertFindDirectory(status_t status, const char *where);
|
|
||||||
status_t _LaunchByPath(const char *path);
|
|
||||||
status_t _LaunchBySig(const char *sig);
|
|
||||||
void _LoadSettings();
|
|
||||||
void _SaveSettings();
|
|
||||||
|
|
||||||
BBitmap* fSegments;
|
|
||||||
VolumeSlider* fVolumeSlider;
|
|
||||||
bool fDontBeep;
|
|
||||||
// don't beep on volume change
|
|
||||||
int32 fVolumeWhich;
|
|
||||||
// which volume parameter to act on (Mixer/Phys.Output)
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// This is the exported function that will be used by Deskbar
|
|
||||||
// to create and add the replicant
|
|
||||||
//
|
|
||||||
extern "C" _EXPORT BView* instantiate_deskbar_item();
|
|
||||||
|
|
||||||
BView *
|
|
||||||
instantiate_deskbar_item()
|
|
||||||
{
|
|
||||||
return new MediaReplicant(BRect(0, 0, 16, 16), VOLUME_CTL_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MediaReplicant::MediaReplicant(BRect frame, const char *name,
|
|
||||||
uint32 resizeMask, uint32 flags)
|
|
||||||
: BView(frame, name, resizeMask, flags),
|
|
||||||
fVolumeSlider(NULL)
|
|
||||||
{
|
|
||||||
// Background Bitmap
|
|
||||||
fSegments = new BBitmap(BRect(0, 0, kSpeakerWidth - 1, kSpeakerHeight - 1), B_CMAP8);
|
|
||||||
fSegments->SetBits(kSpeakerBits, kSpeakerWidth*kSpeakerHeight, 0, B_CMAP8);
|
|
||||||
_LoadSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MediaReplicant::MediaReplicant(BMessage *message)
|
|
||||||
: BView(message),
|
|
||||||
fVolumeSlider(NULL)
|
|
||||||
{
|
|
||||||
// Background Bitmap
|
|
||||||
fSegments = new BBitmap(BRect(0, 0, 16 - 1, 16 - 1), B_CMAP8);
|
|
||||||
fSegments->SetBits(kSpeakerBits, 16*16, 0, B_CMAP8);
|
|
||||||
_LoadSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MediaReplicant::~MediaReplicant()
|
|
||||||
{
|
|
||||||
delete fSegments;
|
|
||||||
_SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MediaReplicant *
|
|
||||||
MediaReplicant::Instantiate(BMessage *data)
|
|
||||||
{
|
|
||||||
if (!validate_instantiation(data, VOLUME_CTL_NAME))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return new MediaReplicant(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
MediaReplicant::Archive(BMessage *data, bool deep) const
|
|
||||||
{
|
|
||||||
status_t status = BView::Archive(data, deep);
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
return data->AddString("add_on", kAppSignature);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::MessageReceived(BMessage *message)
|
|
||||||
{
|
|
||||||
switch (message->what) {
|
|
||||||
case B_ABOUT_REQUESTED:
|
|
||||||
(new BAlert("About Volume Control", "Volume Control (Replicant)\n"
|
|
||||||
" Brought to you by Jérôme DUVAL.\n\n"
|
|
||||||
"Copyright " B_UTF8_COPYRIGHT "2003-2009, Haiku","OK"))->Go(NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPEN_MEDIA_PLAYER:
|
|
||||||
{
|
|
||||||
BPath mediaPlayerPath;
|
|
||||||
status_t status = find_directory(B_BEOS_APPS_DIRECTORY, &mediaPlayerPath);
|
|
||||||
if (status != B_OK) {
|
|
||||||
_AlertFindDirectory(status, __PRETTY_FUNCTION__);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mediaPlayerPath.Append("MediaPlayer");
|
|
||||||
|
|
||||||
// launch the media player app
|
|
||||||
if (_LaunchBySig("application/x-vnd.Haiku-MediaPlayer") == B_OK
|
|
||||||
|| _LaunchBySig("application/x-vnd.Be.MediaPlayer") == B_OK
|
|
||||||
|| _LaunchByPath(mediaPlayerPath.Path()) == B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
(new BAlert("desklink", "Couldn't launch MediaPlayer", "OK"))->Go();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MEDIA_SETTINGS:
|
|
||||||
{
|
|
||||||
BPath mediaPrefsPath;
|
|
||||||
status_t status = find_directory(B_BEOS_PREFERENCES_DIRECTORY,
|
|
||||||
&mediaPrefsPath);
|
|
||||||
if (status != B_OK) {
|
|
||||||
_AlertFindDirectory(status, __PRETTY_FUNCTION__);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mediaPrefsPath.Append("Media");
|
|
||||||
|
|
||||||
// launch the media prefs app
|
|
||||||
if (_LaunchBySig("application/x-vnd.Haiku-Media") == B_OK
|
|
||||||
|| _LaunchBySig("application/x-vnd.Be.MediaPrefs") == B_OK
|
|
||||||
|| _LaunchByPath(mediaPrefsPath.Path()) == B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
(new BAlert("desklink", "Couldn't launch Media Preferences", "OK"))->Go();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SOUND_SETTINGS:
|
|
||||||
{
|
|
||||||
BPath soundsPrefsPath;
|
|
||||||
status_t status = find_directory(B_BEOS_PREFERENCES_DIRECTORY,
|
|
||||||
&soundsPrefsPath);
|
|
||||||
if (status != B_OK) {
|
|
||||||
_AlertFindDirectory(status, __PRETTY_FUNCTION__);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
soundsPrefsPath.Append("Sounds");
|
|
||||||
|
|
||||||
// launch the sounds prefs app
|
|
||||||
if (_LaunchBySig("application/x-vnd.Haiku-Sounds") == B_OK
|
|
||||||
|| _LaunchBySig("application/x-vnd.Be.SoundsPrefs") == B_OK
|
|
||||||
|| _LaunchByPath(soundsPrefsPath.Path()) == B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
(new BAlert("desklink", "Couldn't launch Sounds Preferences", "OK"))->Go();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TOGGLE_DONT_BEEP:
|
|
||||||
fDontBeep = !fDontBeep;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SET_VOLUME_WHICH:
|
|
||||||
message->FindInt32("volwhich", &fVolumeWhich);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_MOUSE_WHEEL_CHANGED:
|
|
||||||
{
|
|
||||||
float dy;
|
|
||||||
if (message->FindFloat("be:wheel_delta_y", &dy) == B_OK
|
|
||||||
&& dy != 0.0) {
|
|
||||||
MixerControl mixerControl(fVolumeWhich);
|
|
||||||
mixerControl.ChangeVolumeBy(dy < 0 ? 20 : -20);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
BView::MessageReceived(message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
MediaReplicant::_LaunchByPath(const char *path)
|
|
||||||
{
|
|
||||||
BEntry ent;
|
|
||||||
entry_ref ref;
|
|
||||||
app_info appInfo;
|
|
||||||
status_t err;
|
|
||||||
|
|
||||||
err = ent.SetTo(path);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
err = ent.GetRef(&ref);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
err = be_roster->Launch(&ref);
|
|
||||||
if (err != B_ALREADY_RUNNING)
|
|
||||||
return err; // should be B_OK or fatal error
|
|
||||||
err = be_roster->GetAppInfo(&ref, &appInfo);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
return be_roster->ActivateApp(appInfo.team);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
MediaReplicant::_LaunchBySig(const char *sig)
|
|
||||||
{
|
|
||||||
app_info appInfo;
|
|
||||||
status_t err;
|
|
||||||
|
|
||||||
err = be_roster->Launch(sig);
|
|
||||||
if (err != B_ALREADY_RUNNING)
|
|
||||||
return err; // should be B_OK or fatal error
|
|
||||||
err = be_roster->GetAppInfo(sig, &appInfo);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
return be_roster->ActivateApp(appInfo.team);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::AttachedToWindow()
|
|
||||||
{
|
|
||||||
BView *parent = Parent();
|
|
||||||
if (parent)
|
|
||||||
SetViewColor(parent->ViewColor());
|
|
||||||
|
|
||||||
BView::AttachedToWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::Draw(BRect rect)
|
|
||||||
{
|
|
||||||
BView::Draw(rect);
|
|
||||||
|
|
||||||
SetDrawingMode(B_OP_OVER);
|
|
||||||
DrawBitmap(fSegments);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::MouseDown(BPoint point)
|
|
||||||
{
|
|
||||||
uint32 mouseButtons;
|
|
||||||
BPoint where;
|
|
||||||
GetMouse(&where, &mouseButtons, true);
|
|
||||||
|
|
||||||
where = ConvertToScreen(point);
|
|
||||||
|
|
||||||
if (mouseButtons & B_SECONDARY_MOUSE_BUTTON) {
|
|
||||||
BPopUpMenu *menu = new BPopUpMenu("", false, false);
|
|
||||||
menu->SetFont(be_plain_font);
|
|
||||||
menu->AddItem(new BMenuItem("Media Preferences" B_UTF8_ELLIPSIS, new BMessage(MEDIA_SETTINGS)));
|
|
||||||
menu->AddItem(new BMenuItem("Sound Preferences" B_UTF8_ELLIPSIS, new BMessage(SOUND_SETTINGS)));
|
|
||||||
menu->AddSeparatorItem();
|
|
||||||
menu->AddItem(new BMenuItem("Open MediaPlayer", new BMessage(OPEN_MEDIA_PLAYER)));
|
|
||||||
menu->AddSeparatorItem();
|
|
||||||
BMenuItem *tmpItem = new BMenuItem("Don't beep", new BMessage(TOGGLE_DONT_BEEP));
|
|
||||||
menu->AddItem(tmpItem);
|
|
||||||
tmpItem->SetMarked(fDontBeep);
|
|
||||||
BMenu *volMenu = new BMenu("Act On");
|
|
||||||
volMenu->SetFont(be_plain_font);
|
|
||||||
BMessage *msg;
|
|
||||||
msg = new BMessage(SET_VOLUME_WHICH);
|
|
||||||
msg->AddInt32("volwhich", VOLUME_USE_MIXER);
|
|
||||||
tmpItem = new BMenuItem("System Mixer", msg);
|
|
||||||
tmpItem->SetMarked(fVolumeWhich == VOLUME_USE_MIXER);
|
|
||||||
volMenu->AddItem(tmpItem);
|
|
||||||
msg = new BMessage(SET_VOLUME_WHICH);
|
|
||||||
msg->AddInt32("volwhich", VOLUME_USE_PHYS_OUTPUT);
|
|
||||||
tmpItem = new BMenuItem("Physical Output", msg);
|
|
||||||
volMenu->AddItem(tmpItem);
|
|
||||||
tmpItem->SetMarked(fVolumeWhich == VOLUME_USE_PHYS_OUTPUT);
|
|
||||||
menu->AddItem(volMenu);
|
|
||||||
|
|
||||||
menu->AddSeparatorItem();
|
|
||||||
menu->SetFont(be_plain_font);
|
|
||||||
menu->AddItem(new BMenuItem("About" B_UTF8_ELLIPSIS,
|
|
||||||
new BMessage(B_ABOUT_REQUESTED)));
|
|
||||||
|
|
||||||
menu->SetTargetForItems(this);
|
|
||||||
volMenu->SetTargetForItems(this);
|
|
||||||
menu->Go(where, true, true, BRect(where - BPoint(4, 4),
|
|
||||||
where + BPoint(4, 4)));
|
|
||||||
} else if (mouseButtons & B_PRIMARY_MOUSE_BUTTON) {
|
|
||||||
// Show VolumeSlider
|
|
||||||
fVolumeSlider = new VolumeSlider(BRect(where.x, where.y, where.x + 207, where.y + 19),
|
|
||||||
fDontBeep, fVolumeWhich);
|
|
||||||
fVolumeSlider->Show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::MouseUp(BPoint point)
|
|
||||||
{
|
|
||||||
// don't Quit() ! thanks for FFM users
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::_LoadSettings()
|
|
||||||
{
|
|
||||||
fDontBeep = false;
|
|
||||||
fVolumeWhich = VOLUME_USE_MIXER;
|
|
||||||
|
|
||||||
BPath p;
|
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &p, false) < B_OK)
|
|
||||||
return;
|
|
||||||
p.SetTo(p.Path(), SETTINGS_FILE);
|
|
||||||
BFile settings(p.Path(), B_READ_ONLY);
|
|
||||||
if (settings.InitCheck() < B_OK)
|
|
||||||
return;
|
|
||||||
BMessage msg;
|
|
||||||
if (msg.Unflatten(&settings) < B_OK)
|
|
||||||
return;
|
|
||||||
msg.FindInt32("volwhich", &fVolumeWhich);
|
|
||||||
msg.FindBool("dontbeep", &fDontBeep);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::_SaveSettings()
|
|
||||||
{
|
|
||||||
BPath p;
|
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &p, false) < B_OK)
|
|
||||||
return;
|
|
||||||
p.SetTo(p.Path(), SETTINGS_FILE);
|
|
||||||
BFile settings(p.Path(), B_WRITE_ONLY|B_CREATE_FILE|B_ERASE_FILE);
|
|
||||||
if (settings.InitCheck() < B_OK)
|
|
||||||
return;
|
|
||||||
BMessage msg('CNFG');
|
|
||||||
msg.AddInt32("volwhich", fVolumeWhich);
|
|
||||||
msg.AddBool("dontbeep", fDontBeep);
|
|
||||||
ssize_t len=0;
|
|
||||||
if (msg.Flatten(&settings, &len) < B_OK)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MediaReplicant::_AlertFindDirectory(status_t status, const char *where)
|
|
||||||
{
|
|
||||||
BString errorMessage;
|
|
||||||
errorMessage << "At " << where << "\n";
|
|
||||||
errorMessage << "find_directory() failed. \nReason: ";
|
|
||||||
errorMessage << strerror(status);
|
|
||||||
(new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL,
|
|
||||||
B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int, char **argv)
|
main(int, char **argv)
|
||||||
{
|
{
|
||||||
@@ -444,31 +47,35 @@ main(int, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (strcmp(argv[i], "--list") == 0) {
|
if (strcmp(argv[i], "--list") == 0) {
|
||||||
int32 i, found = 0, count;
|
int32 count = deskbar.CountItems();
|
||||||
count = deskbar.CountItems();
|
|
||||||
printf("Deskbar items:\n");
|
printf("Deskbar items:\n");
|
||||||
// the API is doomed, so don't try to enum for too long
|
|
||||||
for (i = 0; (found < count) && (i >= 0) && (i < 5000); i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
const char scratch[2] = ""; // BDeskbar is buggy
|
const char *name = NULL;
|
||||||
const char *name=scratch;
|
if (deskbar.GetItemInfo(i, &name) == B_OK) {
|
||||||
if (deskbar.GetItemInfo(i, &name) >= B_OK) {
|
|
||||||
found++;
|
|
||||||
printf("Item %ld: '%s'\n", i, name);
|
printf("Item %ld: '%s'\n", i, name);
|
||||||
free((void *)name); // INTENDED
|
free((void *)name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
if (strcmp(argv[i], "--add-volume") == 0) {
|
||||||
if (strcmp(argv[i], "--volume") == 0) {
|
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
if (get_ref_for_path(argv[0], &ref) == B_OK) {
|
if (get_ref_for_path(argv[0], &ref) == B_OK) {
|
||||||
deskbar.AddItem(&ref);
|
deskbar.AddItem(&ref);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
if (strcmp(argv[i], "--volume-control") == 0) {
|
||||||
|
BWindow* window = new VolumeWindow(BRect(200, 150, 400, 200));
|
||||||
|
window->Show();
|
||||||
|
|
||||||
|
wait_for_thread(window->Thread(), NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp(argv[i], "--remove", 8) == 0) {
|
if (strncmp(argv[i], "--remove", 8) == 0) {
|
||||||
BString replicant = "DeskButton";
|
BString replicant = "DeskButton";
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2009, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Jérôme Duval
|
||||||
|
* François Revol
|
||||||
|
* Marcus Overhagen
|
||||||
|
* Jonas Sundström
|
||||||
|
*/
|
||||||
|
#ifndef DESKLINK_H
|
||||||
|
#define DESKLINK_H
|
||||||
|
|
||||||
|
|
||||||
|
extern const char *kAppSignature;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DESKLINK_H
|
||||||
Reference in New Issue
Block a user