Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

audiowidget.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 #include "audiowidget.h"
00021 #include "mediaplayerstate.h"
00022 
00023 /* OPIE */
00024 #include <qpe/qpeapplication.h>
00025 #include <qpe/config.h>
00026 #include <opie2/odebug.h>
00027 #include <opie2/oresource.h>
00028 
00029 /* QT */
00030 #include <qdir.h>
00031 
00032 /* STD */
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 
00036 extern MediaPlayerState *mediaPlayerState;
00037 
00038 
00039 static const int xo = -2; // movable x offset
00040 static const int yo = 22; // movable y offset
00041 
00042 using namespace Opie::Ui;
00043 struct MediaButton {
00044    bool isToggle, isHeld, isDown;
00045 };
00046 
00047 //Layout information for the audioButtons (and if it is a toggle button or not)
00048 MediaButton audioButtons[] = {
00049    { TRUE,  FALSE, FALSE }, // play
00050    { FALSE, FALSE, FALSE }, // stop
00051    { FALSE, FALSE, FALSE }, // next
00052    { FALSE, FALSE, FALSE }, // previous
00053    { FALSE, FALSE, FALSE }, // volume up
00054    { FALSE, FALSE, FALSE }, // volume down
00055    { TRUE,  FALSE, FALSE }, // repeat/loop
00056    { FALSE, FALSE, FALSE }, // playlist
00057    { FALSE, FALSE, FALSE }, // forward
00058    { FALSE, FALSE, FALSE }  // back
00059 };
00060 
00061 const char *skin_mask_file_names[10] = {
00062    "play", "stop", "next", "prev", "up",
00063    "down", "loop", "playlist", "forward", "back"
00064 };
00065 
00066 static void changeTextColor( QWidget *w ) {
00067    QPalette p = w->palette();
00068    p.setBrush( QColorGroup::Background, QColor( 167, 212, 167 ) );
00069    p.setBrush( QColorGroup::Base, QColor( 167, 212, 167 ) );
00070    w->setPalette( p );
00071 }
00072 
00073 static const int numButtons = (sizeof(audioButtons)/sizeof(MediaButton));
00074 
00075 AudioWidget::AudioWidget(QWidget* parent, const char* name, WFlags f) :
00076     QWidget( parent, name, f ), songInfo( this ), slider( Qt::Horizontal, this ),  time( this )
00077 {
00078     setCaption( tr("OpiePlayer") );
00079     //    odebug << "<<<<<audioWidget" << oendl;
00080 
00081     Config cfg("OpiePlayer");
00082     cfg.setGroup("Options");
00083     skin = cfg.readEntry("Skin","default");
00084     //skin = "scaleTest";
00085 // color of background, frame, degree of transparency
00086 
00087 //    QString skinPath = "opieplayer/skins/" + skin;
00088     QString skinPath;
00089     skinPath = "opieplayer2/skins/" + skin;
00090     if(!QDir(QString(getenv("OPIEDIR")) +"/pics/"+skinPath).exists())
00091        skinPath = "opieplayer2/skins/default";
00092 
00093     //    odebug << "skin path " + skinPath << oendl;
00094 
00095     pixBg = new QPixmap( Opie::Core::OResource::loadPixmap( QString("%1/background").arg(skinPath) ) );
00096     imgUp = new QImage( Opie::Core::OResource::loadImage( QString("%1/skin_up").arg(skinPath) ) );
00097     imgDn = new QImage( Opie::Core::OResource::loadImage( QString("%1/skin_down").arg(skinPath) ) );
00098 
00099     imgButtonMask = new QImage( imgUp->width(), imgUp->height(), 8, 255 );
00100     imgButtonMask->fill( 0 );
00101 
00102     for ( int i = 0; i < 10; i++ ) {
00103         QString filename = QString(getenv("OPIEDIR")) + "/pics/" + skinPath + "/skin_mask_" + skin_mask_file_names[i] + ".png";
00104         masks[i] = new QBitmap( filename );
00105 
00106         if ( !masks[i]->isNull() ) {
00107             QImage imgMask = masks[i]->convertToImage();
00108             uchar **dest = imgButtonMask->jumpTable();
00109             for ( int y = 0; y < imgUp->height(); y++ ) {
00110                 uchar *line = dest[y];
00111                 for ( int x = 0; x < imgUp->width(); x++ )
00112                     if ( !qRed( imgMask.pixel( x, y ) ) )
00113                         line[x] = i + 1;
00114             }
00115         }
00116 
00117     }
00118 
00119     for ( int i = 0; i < 11; i++ ) {
00120         buttonPixUp[i] = NULL;
00121         buttonPixDown[i] = NULL;
00122     }
00123 
00124         QWidget *d = QApplication::desktop();
00125         int width = d->width();
00126         int height = d->height();
00127 
00128     if( (width != pixBg->width() ) || (height != pixBg->height() ) ) {
00129 //              odebug << "<<<<<<<< scale image >>>>>>>>>>>>" << oendl;
00130                 QImage img;
00131                 img = pixBg->convertToImage();
00132                 pixBg->convertFromImage( img.smoothScale( width, height));
00133         }
00134     setBackgroundPixmap( *pixBg);
00135 
00136     songInfo.setFocusPolicy( QWidget::NoFocus );
00137 
00138 //    changeTextColor( &songInfo );
00139 //    songInfo.setBackgroundColor( QColor( 167, 212, 167 ));
00140 //    songInfo.setFrameStyle( QFrame::NoFrame);
00141 //    songInfo.setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
00142       //NoFrame
00143 //    songInfo.setForegroundColor(Qt::white);
00144 
00145     slider.setFixedHeight( 20 );
00146     slider.setMinValue( 0 );
00147     slider.setMaxValue( 1 );
00148     slider.setFocusPolicy( QWidget::NoFocus );
00149 
00150     slider.setBackgroundPixmap( *pixBg );
00151 
00152     time.setFocusPolicy( QWidget::NoFocus );
00153     time.setAlignment( Qt::AlignCenter );
00154     time.setFrame(FALSE);
00155     changeTextColor( &time );
00156 
00157     resizeEvent( NULL );
00158 
00159     connect( &slider,           SIGNAL( sliderPressed() ),      this, SLOT( sliderPressed() ) );
00160     connect( &slider,           SIGNAL( sliderReleased() ),     this, SLOT( sliderReleased() ) );
00161 
00162     connect( mediaPlayerState, SIGNAL( lengthChanged(long) ),  this, SLOT( setLength(long) ) );
00163     connect( mediaPlayerState, SIGNAL( viewChanged(char) ),    this, SLOT( setView(char) ) );
00164     connect( mediaPlayerState, SIGNAL( loopingToggled(bool) ), this, SLOT( setLooping(bool) ) );
00165 //    connect( mediaPlayerState, SIGNAL( pausedToggled(bool) ),  this, SLOT( setPaused(bool) ) );
00166     connect( mediaPlayerState, SIGNAL( playingToggled(bool) ), this, SLOT( setPlaying(bool) ) );
00167 
00168     // Intialise state
00169     setLength( mediaPlayerState->length() );
00170     setPosition( mediaPlayerState->position() );
00171     setLooping( mediaPlayerState->fullscreen() );
00172 //    setPaused( mediaPlayerState->paused() );
00173     setPlaying( mediaPlayerState->playing() );
00174                 this->setFocus();
00175                 if(this->x() < 0 || this->y() < 0)
00176                         this->move(0,0);
00177 }
00178 
00179 
00180 AudioWidget::~AudioWidget() {
00181    //       setPlaying( false);
00182 
00183     for ( int i = 0; i < 10; i++ ) {
00184         if(buttonPixUp[i]) delete buttonPixUp[i];
00185         if(buttonPixDown[i]) delete buttonPixDown[i];
00186     }
00187     if(pixBg) delete pixBg;
00188     if(imgUp) delete imgUp;
00189     if(imgDn) delete imgDn;
00190     if(imgButtonMask) delete imgButtonMask;
00191     for ( int i = 0; i < 10; i++ ) {
00192         if(masks[i]) delete masks[i];
00193     }
00194 }
00195 
00196 
00197 QPixmap *combineImageWithBackground( QImage img, QPixmap bg, QPoint offset ) {
00198     QPixmap pix( img.width(), img.height() );
00199     QPainter p( &pix );
00200     p.drawTiledPixmap( pix.rect(), bg, offset );
00201     p.drawImage( 0, 0, img );
00202     return new QPixmap( pix );
00203 }
00204 
00205 
00206 QPixmap *maskPixToMask( QPixmap pix, QBitmap mask )
00207 {
00208     QPixmap *pixmap = new QPixmap( pix );
00209     pixmap->setMask( mask );
00210     return pixmap;
00211 }
00212 
00213 
00214 
00215 void AudioWidget::resizeEvent( QResizeEvent * ) {
00216     int h = height();
00217     int w = width();
00218 
00219     songInfo.setGeometry( QRect( 2, 10, w - 4, 20 ) );
00220     slider.setFixedWidth( w - 110 );
00221     slider.setGeometry( QRect( 15, h - 30, w - 90, 20 ) );
00222     slider.setBackgroundOrigin( QWidget::ParentOrigin );
00223     time.setGeometry( QRect( w - 85, h - 30, 70, 20 ) );
00224 
00225     xoff = ( w - imgUp->width() ) / 2;
00226     yoff = (( h - imgUp->height() ) / 2) - 10;
00227     QPoint p( xoff, yoff );
00228 
00229     QPixmap *pixUp = combineImageWithBackground( *imgUp, *pixBg, p );
00230     QPixmap *pixDn = combineImageWithBackground( *imgDn, *pixBg, p );
00231 
00232     for ( int i = 0; i < 10; i++ ) {
00233         if ( !masks[i]->isNull() ) {
00234             delete buttonPixUp[i];
00235             delete buttonPixDown[i];
00236             buttonPixUp[i] = maskPixToMask( *pixUp, *masks[i] );
00237             buttonPixDown[i] = maskPixToMask( *pixDn, *masks[i] );
00238         }
00239     }
00240 
00241     delete pixUp;
00242     delete pixDn;
00243 }
00244 
00245 
00246 static bool audioSliderBeingMoved = FALSE;
00247 
00248 void AudioWidget::sliderPressed() {
00249     audioSliderBeingMoved = TRUE;
00250 }
00251 
00252 
00253 void AudioWidget::sliderReleased() {
00254     audioSliderBeingMoved = FALSE;
00255     if ( slider.width() == 0 )
00256   return;
00257     long val = long((double)slider.value() * mediaPlayerState->length() / slider.width());
00258     mediaPlayerState->setPosition( val );
00259 }
00260 
00261 
00262 void AudioWidget::setPosition( long i ) {
00263 //    odebug << "set position " << i << "" << oendl;
00264     long length = mediaPlayerState->length();
00265     updateSlider( i, length );
00266 }
00267 
00268 
00269 void AudioWidget::setLength( long max ) {
00270     updateSlider( mediaPlayerState->position(), max );
00271 }
00272 
00273 
00274 void AudioWidget::setView( char view ) {
00275 
00276     if (mediaPlayerState->isStreaming) {
00277         if( !slider.isHidden()) slider.hide();
00278         disconnect( mediaPlayerState, SIGNAL( positionChanged(long) ),this, SLOT( setPosition(long) ) );
00279         disconnect( mediaPlayerState, SIGNAL( positionUpdated(long) ),this, SLOT( setPosition(long) ) );
00280     } else {
00281 // this stops the slider from being moved, thus
00282           // does not stop stream when it reaches the end
00283         slider.show();
00284         connect( mediaPlayerState, SIGNAL( positionChanged(long) ),this, SLOT( setPosition(long) ) );
00285         connect( mediaPlayerState, SIGNAL( positionUpdated(long) ),this, SLOT( setPosition(long) ) );
00286     }
00287 
00288     if ( view == 'a' ) {
00289         startTimer( 150 );
00290 //        show();
00291         QPEApplication::showWidget( this );
00292     } else {
00293         killTimers();
00294         hide();
00295     }
00296 
00297 }
00298 
00299 
00300 static QString timeAsString( long length ) {
00301     length /= 44100;
00302     int minutes = length / 60;
00303     int seconds = length % 60;
00304     return QString("%1:%2%3").arg( minutes ).arg( seconds / 10 ).arg( seconds % 10 );
00305 }
00306 
00307 void AudioWidget::updateSlider( long i, long max ) {
00308 this->setFocus();
00309  time.setText( timeAsString( i ) + " / " + timeAsString( max ) );
00310 
00311     if ( max == 0 )
00312   return;
00313     // Will flicker too much if we don't do this
00314     // Scale to something reasonable
00315     int width = slider.width();
00316     int val = int((double)i * width / max);
00317     if ( !audioSliderBeingMoved ) {
00318   if ( slider.value() != val )
00319       slider.setValue( val );
00320   if ( slider.maxValue() != width )
00321       slider.setMaxValue( width );
00322     }
00323 }
00324 
00325 
00326 void AudioWidget::setToggleButton( int i, bool down ) {
00327     if ( down != audioButtons[i].isDown )
00328   toggleButton( i );
00329 }
00330 
00331 
00332 void AudioWidget::toggleButton( int i ) {
00333     audioButtons[i].isDown = !audioButtons[i].isDown;
00334     QPainter p(this);
00335     paintButton ( &p, i );
00336 }
00337 
00338 
00339 void AudioWidget::paintButton( QPainter *p, int i ) {
00340     if ( audioButtons[i].isDown )
00341         p->drawPixmap( xoff, yoff, *buttonPixDown[i] );
00342     else
00343         p->drawPixmap( xoff, yoff, *buttonPixUp[i] );
00344 }
00345 
00346 
00347 void AudioWidget::timerEvent( QTimerEvent * ) {
00348 /*
00349     int x = audioButtons[AudioPlay].xPos;
00350  int y = audioButtons[AudioPlay].yPos;
00351  QPainter p( this );
00352  // Optimize to only draw the little bit of the changing images which is different
00353  p.drawPixmap( x + 14, y +  8, *pixmaps[3], 32 * frame, 0, 32, 32 );
00354  p.drawPixmap( x + 37, y + 37, *pixmaps[2], 18 * AudioPlay, 0, 6, 3 );
00355 */
00356 /*
00357     static int frame = 0;
00358     if ( !mediaPlayerState->paused() && audioButtons[ AudioPlay ].isDown ) {
00359   frame = frame >= 7 ? 0 : frame + 1;
00360     }
00361     */
00362 }
00363 
00364 
00365 void AudioWidget::mouseMoveEvent( QMouseEvent *event ) {
00366     for ( int i = 0; i < numButtons; i++ ) {
00367         if ( event->state() == QMouseEvent::LeftButton ) {
00368 
00369               // The test to see if the mouse click is inside the button or not
00370             int x = event->pos().x() - xoff;
00371             int y = event->pos().y() - yoff;
00372 
00373             bool isOnButton = ( x > 0 && y > 0 && x < imgButtonMask->width()
00374                                 && y < imgButtonMask->height() && imgButtonMask->pixelIndex( x, y ) == i + 1 );
00375 
00376 //              if ( isOnButton && i == AudioVolumeUp )
00377 //                  odebug << "on up" << oendl;
00378 
00379             if ( isOnButton && !audioButtons[i].isHeld ) {
00380                 audioButtons[i].isHeld = TRUE;
00381                 toggleButton(i);
00382                 switch (i) {
00383                   case AudioVolumeUp:
00384                      //                      odebug << "more clicked" << oendl;
00385                       emit moreClicked();
00386                       return;
00387                   case AudioVolumeDown:
00388                      //                      odebug << "less clicked" << oendl;
00389                       emit lessClicked();
00390                       return;
00391                 case AudioForward:
00392                     emit forwardClicked();
00393                     return;
00394                 case AudioBack:
00395                     emit backClicked();
00396                     return;
00397                 }
00398             } else if ( !isOnButton && audioButtons[i].isHeld ) {
00399                 audioButtons[i].isHeld = FALSE;
00400                 toggleButton(i);
00401             }
00402         } else {
00403             if ( audioButtons[i].isHeld ) {
00404                 audioButtons[i].isHeld = FALSE;
00405                 if ( !audioButtons[i].isToggle )
00406                     setToggleButton( i, FALSE );
00407                 switch (i) {
00408                 case AudioPlay:
00409                     if( mediaPlayerState->isPaused ) {
00410                         mediaPlayerState->setPaused( FALSE );
00411                         return;
00412                     } else if( !mediaPlayerState->isPaused ) {
00413                         mediaPlayerState->setPaused( TRUE );
00414                         return;
00415                     }
00416 //                  case AudioPlay:       mediaPlayerState->setPlaying(audioButtons[i].isDown); return;
00417                   case AudioStop:       mediaPlayerState->setPlaying(FALSE); return;
00418 //                  case AudioPause:      mediaPlayerState->setPaused(audioButtons[i].isDown); return;
00419                   case AudioNext:       mediaPlayerState->setNext(); return;
00420                   case AudioPrevious:   mediaPlayerState->setPrev(); return;
00421                   case AudioLoop:       mediaPlayerState->setLooping(audioButtons[i].isDown); return;
00422                   case AudioVolumeUp:   emit moreReleased(); return;
00423                   case AudioVolumeDown: emit lessReleased(); return;
00424                   case AudioPlayList:   mediaPlayerState->setList();  return;
00425                 }
00426             }
00427         }
00428     }
00429 }
00430 
00431 
00432 
00433 void AudioWidget::mousePressEvent( QMouseEvent *event ) {
00434     mouseMoveEvent( event );
00435 }
00436 
00437 
00438 void AudioWidget::mouseReleaseEvent( QMouseEvent *event ) {
00439     mouseMoveEvent( event );
00440 }
00441 
00442 
00443 void AudioWidget::showEvent( QShowEvent* ) {
00444     QMouseEvent event( QEvent::MouseMove, QPoint( 0, 0 ), 0, 0 );
00445     mouseMoveEvent( &event );
00446 }
00447 
00448 
00449 void AudioWidget::closeEvent( QCloseEvent* ) {
00450     mediaPlayerState->setList();
00451 }
00452 
00453 
00454 void AudioWidget::paintEvent( QPaintEvent * pe) {
00455     if ( !pe->erased() ) {
00456           // Combine with background and double buffer
00457         QPixmap pix( pe->rect().size() );
00458         QPainter p( &pix );
00459         p.translate( -pe->rect().topLeft().x(), -pe->rect().topLeft().y() );
00460         p.drawTiledPixmap( pe->rect(), *pixBg, pe->rect().topLeft() );
00461         for ( int i = 0; i < numButtons; i++ )
00462             paintButton( &p, i );
00463         QPainter p2( this );
00464         p2.drawPixmap( pe->rect().topLeft(), pix );
00465     } else {
00466         QPainter p( this );
00467         for ( int i = 0; i < numButtons; i++ )
00468             paintButton( &p, i );
00469     }
00470 }
00471 
00472 void AudioWidget::keyReleaseEvent( QKeyEvent *e)
00473 {
00474     switch ( e->key() ) {
00476       case Key_Home:
00477           break;
00478       case Key_F9: //activity
00479            hide();
00480 //           odebug << "Audio F9" << oendl;
00481           break;
00482       case Key_F10: //contacts
00483           break;
00484       case Key_F11: //menu
00485           break;
00486       case Key_F12: //home
00487           break;
00488       case Key_F13: //mail
00489           break;
00490       case Key_Space: {
00491 
00492           if(mediaPlayerState->playing()) {
00493 //                toggleButton(1);
00494               mediaPlayerState->setPlaying(FALSE);
00495 //                toggleButton(1);
00496           } else {
00497 //                toggleButton(0);
00498               mediaPlayerState->setPlaying(TRUE);
00499 //                toggleButton(0);
00500           }
00501       }
00502           break;
00503       case Key_Down: //volume
00504 //            toggleButton(6);
00505           emit lessClicked();
00506           emit lessReleased();
00507 //          toggleButton(6);
00508           break;
00509       case Key_Up:   //volume
00510 //           toggleButton(5);
00511            emit moreClicked();
00512            emit moreReleased();
00513 //           toggleButton(5);
00514            break;
00515       case Key_Right:   //next in playlist
00516 //            toggleButton(3);
00517           mediaPlayerState->setNext();
00518 //            toggleButton(3);
00519           break;
00520       case Key_Left:    // previous in playlist
00521 //            toggleButton(4);
00522           mediaPlayerState->setPrev();
00523 //            toggleButton(4);
00524           break;
00525       case Key_Escape:
00526           break;
00527 
00528     };
00529 }

Generated on Sat Nov 5 16:15:34 2005 for OPIE by  doxygen 1.4.2