You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/noatun/modules/winskin/waSkin.cpp

801 lines
20 KiB

/*
Winamp Skin
Copyright (C) 1999 Martin Vogt
Copyright (C) 2001-2002 Ryan Cumming
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation.
For more information look at the file COPYRIGHT in this package
*/
#include <kconfig.h>
#include <tqstringlist.h>
#include <kglobal.h>
#include <klocale.h>
#include <kiconloader.h>
#include <khelpmenu.h>
#include <kpopupmenu.h>
#include <kurldrag.h>
#include <kstdaction.h>
#include <kaction.h>
#include <tqdragobject.h>
#include <kstandarddirs.h>
#include <kwin.h>
#include <time.h>
#include <noatun/playlist.h>
#include <noatun/app.h>
#include <noatun/stdaction.h>
#include "waSkin.h"
#include "waRegion.h"
#include "waMain.h"
#include "waClutterbar.h"
#include "waDigit.h"
#include "waInfo.h"
#include "waButton.h"
#include "waLabel.h"
#include "waIndicator.h"
#include "waTitleBar.h"
#include "waJumpSlider.h"
#include "waBalanceSlider.h"
#include "waVolumeSlider.h"
#include "waStatus.h"
#include "waSkinManager.h"
#include "waSkinModel.h"
#include "guiSpectrumAnalyser.h"
#include "fileInfo.h"
WaSkin *_waskin_instance = NULL;
WaSkin::WaSkin() : TQWidget(0, "NoatunWinampSkin"), UserInterface()
{
mJumpPressed = false;
mVolumePressed = false;
mBalancePressed = false;
_waskin_instance = this;
// Our really low-level render-y sort of stuff
waSkinModel = new WaSkinModel();
// Skin management stuff
waSkinManager = new WaSkinManager();
createHighLevelElements();
createButtons();
setMinimumSize(tqsizeHint());
setMaximumSize(tqsizeHint());
KWin::setType(this->winId(), NET::Override);
setBackgroundMode(NoBackground);
setAcceptDrops(true);
title_shaded = false;
// These slots make Young Hickory love us
connect( napp, TQT_SIGNAL(hideYourself()), this, TQT_SLOT(hide()) );
connect( napp, TQT_SIGNAL(showYourself()), this, TQT_SLOT(show()) );
connect(napp->player(), TQT_SIGNAL(playlistShown()), this,
TQT_SLOT(playlistShown()));
connect(napp->player(), TQT_SIGNAL(playlistHidden()), this,
TQT_SLOT(playlistHidden()));
connect(napp->player(), TQT_SIGNAL(loopTypeChange(int)), this,
TQT_SLOT(loopChange(int)));
connect(napp->player(), TQT_SIGNAL(newSong()), this, TQT_SLOT(newSong()));
connect(napp->player(), TQT_SIGNAL(timeout()), this, TQT_SLOT(timetick()));
KConfig *config=KGlobal::config();
config->setGroup("Winskin");
TQString skin = config->readEntry("CurrentSkin", WaSkin::defaultSkin());
loadSkin(skin);
setCaption(i18n("Noatun"));
setIcon(SmallIcon("noatun"));
TQObject::connect(waTitleBar, TQT_SIGNAL(shaded()), this, TQT_SLOT(shadeEvent()));
// connect to players signals - so we can update our display if someone else
// changes settings...
connect(napp->player(), TQT_SIGNAL(stopped()), this, TQT_SLOT(slotStopped()));
connect(napp->player(), TQT_SIGNAL(playing()), this, TQT_SLOT(slotPlaying()));
connect(napp->player(), TQT_SIGNAL(paused()), this, TQT_SLOT(slotPaused()));
napp->player()->handleButtons();
playlist->setToggled(napp->playlist()->listVisible());
shuffle->setToggled(false);
repeat->setToggled(false);
waBalanceSlider->setBalanceValue(0);
waVolumeSlider->setVolumeValue(napp->player()->volume());
newSong();
// HACK: We won't get focus events otherwise
setFocusPolicy(TQ_ClickFocus);
show();
}
WaSkin::~WaSkin()
{
delete waSkinManager;
waSkinManager = 0L;
}
void WaSkin::loadSkin(TQString newSkinDir)
{
waSkinManager->loadSkin(newSkinDir);
setMinimumSize(tqsizeHint());
if (title_shaded) {
// waSkinModel::load() resets our skin model :(
waSkinModel->setSkinModel(WA_MODEL_WINDOWSHADE);
setMask(*windowRegion->mainWindowShadeMask());
}
else {
setMask(*windowRegion->mainWindowMask());
}
}
TQSize WaSkin::tqsizeHint() const
{
TQRect temp_rect;
temp_rect = waSkinModel->getGeometry(_WA_SKIN_MAIN);
return temp_rect.size();
}
void WaSkin::createButtons()
{
prev = new WaButton(_WA_MAPPING_CBUTTONS_PREV);
play = new WaButton(_WA_MAPPING_CBUTTONS_PLAY);
pause = new WaButton(_WA_MAPPING_CBUTTONS_PAUSE);
stop = new WaButton(_WA_MAPPING_CBUTTONS_STOP);
next = new WaButton(_WA_MAPPING_CBUTTONS_NEXT);
eject = new WaButton(_WA_MAPPING_CBUTTONS_EJECT);
shuffle = new WaButton(_WA_MAPPING_SHUFFLE);
repeat = new WaButton(_WA_MAPPING_REPEAT);
playlist = new WaButton(_WA_MAPPING_PLAYLIST);
eq = new WaButton(_WA_MAPPING_EQ);
menu = new WaButton(_WA_MAPPING_TITLE_MENU);
menu->setPixmapUp(_WA_SKIN_TITLE_MENU_NORM);
menu->setPixmapDown(_WA_SKIN_TITLE_MENU_PRES);
connect(menu, TQT_SIGNAL(clicked()), this, TQT_SLOT(menuEvent()));
minimize = new WaButton(_WA_MAPPING_TITLE_MIN);
minimize->setPixmapUp(_WA_SKIN_TITLE_MIN_NORM);
minimize->setPixmapDown(_WA_SKIN_TITLE_MIN_PRES);
connect(minimize, TQT_SIGNAL(clicked()), this, TQT_SLOT(minimizeEvent()));
titleshade = new WaButton(_WA_MAPPING_TITLE_SHADE);
titleshade->setPixmapUp(_WA_SKIN_TITLE_SHADE_NORM);
titleshade->setPixmapDown(_WA_SKIN_TITLE_SHADE_PRES);
connect(titleshade, TQT_SIGNAL(clicked()), this, TQT_SLOT(shadeEvent()));
close = new WaButton(_WA_MAPPING_TITLE_CLOSE);
close->setPixmapUp(_WA_SKIN_TITLE_CLOSE_NORM);
close->setPixmapDown(_WA_SKIN_TITLE_CLOSE_PRES);
connect(close, TQT_SIGNAL(clicked()), this, TQT_SLOT(doClose()));
shuffle->setTogglable(true);
shuffle->show();
repeat->setTogglable(true);
playlist->setTogglable(true);
connect(shuffle, TQT_SIGNAL(toggleEvent(bool)),
this, TQT_SLOT(shuffleClickedEvent(bool)));
connect(repeat, TQT_SIGNAL(toggleEvent(bool)),
this, TQT_SLOT(repeatClickedEvent(bool)));
connect(playlist, TQT_SIGNAL(toggleEvent(bool)),
this, TQT_SLOT(playlistClickedEvent(bool)));
connect(eq, TQT_SIGNAL(clicked()),
this, TQT_SLOT(eqClickedEvent()));
prev->setPixmapUp(_WA_SKIN_CBUTTONS_PREV_NORM);
prev->setPixmapDown(_WA_SKIN_CBUTTONS_PREV_PRES);
connect(prev, TQT_SIGNAL(clicked()), napp->player(), TQT_SLOT(back()));
play->setPixmapUp(_WA_SKIN_CBUTTONS_PLAY_NORM);
play->setPixmapDown(_WA_SKIN_CBUTTONS_PLAY_PRES);
connect(play, TQT_SIGNAL(clicked()), this, TQT_SLOT(playCurrentEvent()));
pause->setPixmapUp(_WA_SKIN_CBUTTONS_PAUSE_NORM);
pause->setPixmapDown(_WA_SKIN_CBUTTONS_PAUSE_PRES);
connect(pause, TQT_SIGNAL(clicked()), this, TQT_SLOT(playPauseEvent()));
stop->setPixmapUp(_WA_SKIN_CBUTTONS_STOP_NORM);
stop->setPixmapDown(_WA_SKIN_CBUTTONS_STOP_PRES);
connect(stop, TQT_SIGNAL(clicked()), napp->player(), TQT_SLOT(stop()));
next->setPixmapUp(_WA_SKIN_CBUTTONS_NEXT_NORM);
next->setPixmapDown(_WA_SKIN_CBUTTONS_NEXT_PRES);
connect(next, TQT_SIGNAL(clicked()), napp->player(), TQT_SLOT(forward()));
eject->setPixmapUp(_WA_SKIN_CBUTTONS_EJECT_NORM);
eject->setPixmapDown(_WA_SKIN_CBUTTONS_EJECT_PRESS);
connect(eject, TQT_SIGNAL(clicked()), napp, TQT_SLOT(fileOpen()));
shuffle->setPixmapUp(_WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_NORM);
shuffle->setPixmapDown(_WA_SKIN_SHUFREP_SHUFFLE_NOT_SET_PRES);
shuffle->setPixmapUpSelected(_WA_SKIN_SHUFREP_SHUFFLE_SET_NORM);
shuffle->setPixmapDownSelected(_WA_SKIN_SHUFREP_SHUFFLE_SET_PRES);
shuffle->setToggled(true);
repeat->setPixmapUp(_WA_SKIN_SHUFREP_REPEAT_NOT_SET_NORM);
repeat->setPixmapDown(_WA_SKIN_SHUFREP_REPEAT_NOT_SET_PRES);
repeat->setPixmapUpSelected(_WA_SKIN_SHUFREP_REPEAT_SET_NORM);
repeat->setPixmapDownSelected(_WA_SKIN_SHUFREP_REPEAT_SET_PRES);
eq->setPixmapUp(_WA_SKIN_SHUFREP_ETQ_NOT_SET_NORM);
eq->setPixmapDown(_WA_SKIN_SHUFREP_ETQ_NOT_SET_PRES);
playlist->setPixmapUp(_WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_NORM);
playlist->setPixmapDown( _WA_SKIN_SHUFREP_PLAYLIST_NOT_SET_PRES);
playlist->setPixmapUpSelected(_WA_SKIN_SHUFREP_PLAYLIST_SET_NORM);
playlist->setPixmapDownSelected(_WA_SKIN_SHUFREP_PLAYLIST_SET_PRES);
waClutterbar = new WaClutterbar();
}
void WaSkin::createHighLevelElements()
{
// Two most top-level elements
main = new WaMain();
waTitleBar = new WaTitleBar();
guiSpectrumAnalyser = new GuiSpectrumAnalyser();
waJumpSlider = new WaJumpSlider();
waJumpSlider->buildGui();
waVolumeSlider = new WaVolumeSlider();
waVolumeSlider->buildGui();
connect(waVolumeSlider, TQT_SIGNAL(volumeSetValue(int)),
this, TQT_SLOT(volumeSetValue(int)));
connect(waVolumeSlider, TQT_SIGNAL(sliderPressed()),
this, TQT_SLOT(volumeSliderPressed()));
connect(waVolumeSlider, TQT_SIGNAL(sliderReleased()),
this, TQT_SLOT(volumeSliderReleased()));
waBalanceSlider = new WaBalanceSlider();
waBalanceSlider->buildGui();
connect(waBalanceSlider, TQT_SIGNAL(balanceSetValue(int)),
this, TQT_SLOT(balanceSetValue(int)));
connect(waBalanceSlider, TQT_SIGNAL(sliderPressed()),
this, TQT_SLOT(balanceSliderPressed()));
connect(waBalanceSlider, TQT_SIGNAL(sliderReleased()),
this, TQT_SLOT(balanceSliderReleased()));
waDigit = new WaDigit();
connect(waDigit, TQT_SIGNAL(digitsClicked()), this, TQT_SLOT(digitsClicked()));
waBPS = new WaLabel(_WA_MAPPING_BPS);
waFreq = new WaLabel(_WA_MAPPING_FREQ);
waInfo = new WaInfo();
watqStatus = new WatqStatus();
waStereo = new WaIndicator(_WA_MAPPING_MONOSTER_STEREO, _WA_SKIN_MONOSTER_STEREO_TRUE, _WA_SKIN_MONOSTER_STEREO_FALSE);
waMono = new WaIndicator(_WA_MAPPING_MONOSTER_MONO, _WA_SKIN_MONOSTER_MONO_TRUE, _WA_SKIN_MONOSTER_MONO_FALSE);
connect(waJumpSlider, TQT_SIGNAL(jump(int)), this, TQT_SLOT(jump(int)));
connect(waJumpSlider, TQT_SIGNAL(sliderPressed()),
this, TQT_SLOT(jumpSliderPressed()));
connect(waJumpSlider, TQT_SIGNAL(sliderReleased()),
this, TQT_SLOT(jumpSliderReleased()));
connect(waJumpSlider, TQT_SIGNAL(valueChanged(int)),
this, TQT_SLOT(jumpValueChanged(int)));
}
void WaSkin::setChannels(int val)
{
if (val <= 0) {
waStereo->setState(false);
waMono->setState(false);
} else if (val == 1) {
waStereo->setState(false);
waMono->setState(true);
} else {
waStereo->setState(true);
waMono->setState(false);
}
}
void WaSkin::shade() {
waSkinModel->setSkinModel(WA_MODEL_WINDOWSHADE);
setMinimumSize(tqsizeHint());
setMask(*windowRegion->mainWindowShadeMask());
title_shaded = true;
}
void WaSkin::unshade() {
waSkinModel->setSkinModel(WA_MODEL_NORMAL);
setMinimumSize(tqsizeHint());
setMask(*windowRegion->mainWindowMask());
title_shaded = false;
}
void WaSkin::focusOutEvent( TQFocusEvent * ) {
menu->setPixmapUp(_WA_SKIN_TITLE_MENU_INACTIVE);
menu->update();
minimize->setPixmapUp(_WA_SKIN_TITLE_MIN_INACTIVE);
minimize->update();
titleshade->setPixmapUp(_WA_SKIN_TITLE_SHADE_INACTIVE);
titleshade->update();
close->setPixmapUp(_WA_SKIN_TITLE_CLOSE_INACTIVE);
close->update();
waTitleBar->setState(false);
}
void WaSkin::focusInEvent( TQFocusEvent * ) {
menu->setPixmapUp(_WA_SKIN_TITLE_MENU_NORM);
menu->update();
minimize->setPixmapUp(_WA_SKIN_TITLE_MIN_NORM);
minimize->update();
titleshade->setPixmapUp(_WA_SKIN_TITLE_SHADE_NORM);
titleshade->update();
close->setPixmapUp(_WA_SKIN_TITLE_CLOSE_NORM);
close->update();
waTitleBar->setState(true);
}
void WaSkin::wheelEvent(TQWheelEvent *e) {
// Get the current volume
int newVolume = napp->player()->volume();
// Wheel events return needlessly large "deltas", normalize it a bit
newVolume += e->delta() / 24;
napp->player()->setVolume(newVolume);
}
void WaSkin::repeatClickedEvent(bool)
{
updateLoopStyle();
}
void WaSkin::shuffleClickedEvent(bool)
{
updateLoopStyle();
}
void WaSkin::updateLoopStyle() {
if (shuffle->toggled()) {
napp->player()->loop(Player::Random);
}
else {
int loopVal = repeat->toggled() ? Player::Playlist : Player::None;
napp->player()->loop(loopVal);
}
}
void WaSkin::playlistClickedEvent(bool)
{
napp->playlist()->toggleList();
}
void WaSkin::eqClickedEvent()
{
napp->equalizerView();
}
void WaSkin::jump(int val)
{
if (napp->player()->isStopped()) {
waJumpSlider->setJumpValue(0);
} else {
napp->player()->skipTo((int) (val * 1000));
}
}
void WaSkin::jumpSliderPressed()
{
mJumpPressed = true;
jumpValueChanged(waJumpSlider->jumpValue());
}
void WaSkin::jumpSliderReleased()
{
mJumpPressed = false;
waInfo->setText(getTitleString());
}
void WaSkin::jumpValueChanged(int val)
{
if (mJumpPressed && !napp->player()->isStopped()) {
TQString timeStr = i18n("Seek to: %1/%2 (%3%)").
arg(getTimeString(val * 1000)).
arg(getTimeString(napp->player()->getLength())).
arg((val * 1000 * 100) / napp->player()->getLength());
waInfo->setText(timeStr);
}
}
TQString WaSkin::getTitleString() {
int length;
TQString title = "";
if (!napp->playlist()->current()) {
title = "Noatun ";
title += TQString::number(NOATUN_MAJOR) + ".";
title += TQString::number(NOATUN_MINOR) + ".";
title += TQString::number(NOATUN_PATCHLEVEL);
}
else {
length = napp->playlist()->current().length();
title = napp->playlist()->current().title();
if (length >= 0)
title += " (" + getTimeString(length) + ")";
if (title.length() > 30) {
// It's scrolling; provide the nice, friendly seperator.
title += " *** ";
}
}
return title;
}
TQString WaSkin::getTimeString(int milliseconds, bool truncate) {
int seconds = abs(milliseconds / 1000);
TQString ret = "";
// Do we need to convert to hours:minutes instead of minutes:seconds?
if (truncate && (abs(seconds) >= (100 * 60)))
seconds /= 60;
// Print the optional minus sign, hours/minutes, a colon, and then minutes/seconds.
ret.sprintf("%s%.2d:%.2d", ((milliseconds < 0) ? "-" : ""), seconds / 60, seconds % 60);
return ret;
}
void WaSkin::menuEvent() {
NoatunStdAction::ContextMenu::showContextMenu(mapToGlobal(TQPoint(0, 14)));
}
void WaSkin::minimizeEvent() {
showMinimized();
}
void WaSkin::shadeEvent()
{
if (!title_shaded)
shade();
else
unshade();
}
void WaSkin::doUnload() {
unload();
}
void WaSkin::doClose() {
TQTimer::singleShot(0, this, TQT_SLOT(doUnload()));
}
void WaSkin::dragEnterEvent(TQDragEnterEvent * event)
{
// accept uri drops only
event->accept(KURLDrag::canDecode(event));
}
void WaSkin::dropEvent(TQDropEvent * event)
{
KURL::List uri;
if (KURLDrag::decode(event, uri))
{
for (KURL::List::Iterator i = uri.begin(); i != uri.end(); ++i)
napp->player()->openFile(*i, false);
}
}
void WaSkin::balanceSliderPressed()
{
mBalancePressed = true;
balanceSetValue(0);
}
void WaSkin::balanceSliderReleased()
{
mBalancePressed = false;
waBalanceSlider->setBalanceValue(0);
waInfo->setText(getTitleString());
}
void WaSkin::balanceSetValue(int val)
{
if (val == 0) {
waInfo->setText(i18n("Balance: Center"));
}
else if (val < 0) {
waInfo->setText(i18n("Balance: %1% Left").tqarg(-val));
} else {
waInfo->setText(i18n("Balance: %1% Right").tqarg(val));
}
}
void WaSkin::playCurrentEvent()
{
if (napp->player()->isPaused())
napp->player()->playpause();
else
napp->player()->playCurrent();
}
void WaSkin::playPauseEvent()
{
if (!napp->player()->isStopped())
napp->player()->playpause();
}
void WaSkin::loopChange(int loopType)
{
shuffle->setToggled(loopType == Player::Random);
if (loopType != Player::Random)
repeat->setToggled(loopType != Player::None);
}
void WaSkin::playlistShown()
{
playlist->setToggled(true);
}
void WaSkin::playlistHidden()
{
playlist->setToggled(false);
}
void WaSkin::newSong()
{
if (napp->player()->getLength() == -1)
waJumpSlider->hide();
else
waJumpSlider->show();
mJumpPressed = false;
waJumpSlider->cancelDrag();
timetick();
}
void WaSkin::timetick()
{
int mLength;
if (!mVolumePressed && !mBalancePressed && !mJumpPressed)
waInfo->setText(getTitleString());
if (!napp->player()->current())
return;
mLength = (int) napp->player()->getLength() / 1000;
if (mLength < 0)
mLength = 0;
waJumpSlider->setJumpRange(mLength);
digitsClicked();
int time = 0;
if (napp->player()->current())
time = (int) napp->player()->getTime() / 1000;
if (!mJumpPressed)
waJumpSlider->setJumpValue(time);
waVolumeSlider->setVolumeValue(napp->player()->volume());
}
void WaSkin::digitsClicked() {
if (!waDigit->timeReversed() || (napp->player()->getLength() == -1)) {
// Setting truncate=true means we want setTime to return
// no more than 6 digits (-xx:yy)
if (napp->player()->getTime() != -1)
waDigit->setTime(getTimeString(napp->player()->getTime(), true));
else
waDigit->setTime(getTimeString(0, true));
}
else {
int rem_time = napp->player()->getTime() - napp->player()->getLength();
// Setting truncate=true means we want setTime to return
// no more than 6 digits (-xx:yy)
waDigit->setTime(getTimeString(rem_time, true));
}
}
void WaSkin::volumeSliderPressed()
{
mVolumePressed = true;
volumeSetValue(napp->player()->volume());
}
void WaSkin::volumeSliderReleased()
{
mVolumePressed = false;
waInfo->setText(getTitleString());
}
void WaSkin::volumeSetValue(int val)
{
if (mVolumePressed)
waInfo->setText(i18n("Volume: %1%").tqarg(val));
napp->player()->setVolume(val);
}
void WaSkin::slotPlaying()
{
watqStatus->settqStatus(STATUS_PLAYING);
if (!napp->playlist()->current()) {
return;
}
fileInfo info(napp->playlist()->current());
if (!info.bps())
waBPS->setText("");
else
waBPS->setText(TQString::number(info.bps()));
if (!info.KHz())
waFreq->setText("");
else
waFreq->setText(TQString::number(info.KHz() / 1000));
setChannels(info.channelCount());
guiSpectrumAnalyser->resumeVisualization();
if (napp->player()->getLength() == -1)
waJumpSlider->hide();
else
waJumpSlider->show();
timetick();
}
void WaSkin::slotStopped()
{
watqStatus->settqStatus(STATUS_STOPPED);
waDigit->setTime("");
waBPS->setText("");
waFreq->setText("");
setChannels(0);
waJumpSlider->setJumpValue(0);
// -1 == disable jump bar
waJumpSlider->setJumpRange(-1);
mJumpPressed = false;
waJumpSlider->cancelDrag();
waJumpSlider->hide();
guiSpectrumAnalyser->pauseVisualization();
}
void WaSkin::slotPaused()
{
watqStatus->settqStatus(STATUS_PAUSED);
}
void WaSkin::keyPressEvent(TQKeyEvent *e) {
switch(e->key()) {
case Key_Up:
napp->player()->setVolume(napp->player()->volume() + 5);
break;
case Key_Down:
napp->player()->setVolume(napp->player()->volume() - 5);
break;
case Key_Left:
if (napp->player()->current())
napp->player()->skipTo(napp->player()->getTime() - 5000);
break;
case Key_Right:
if (napp->player()->current())
napp->player()->skipTo(napp->player()->getTime() + 5000);
break;
case Key_Z:
napp->player()->back();
break;
case Key_X:
if (napp->player()->isPaused())
napp->player()->playpause();
else
napp->player()->playCurrent();
break;
case Key_C:
if (!napp->player()->isStopped())
napp->player()->playpause();
break;
case Key_V:
napp->player()->stop();
break;
case Key_B:
napp->player()->forward();
break;
case Key_R:
repeat->setToggled(!repeat->toggled());
updateLoopStyle();
break;
case Key_S:
shuffle->setToggled(!shuffle->toggled());
updateLoopStyle();
break;
}
}
TQString WaSkin::defaultSkin() {
return "Winamp";
}
#include "waSkin.moc"