File indexing completed on 2021-12-21 13:33:28

0001 /*
0002  * Kscd - A simple cd player for the KDE Project
0003  *
0004  * Copyright (c) 1997 Bernd Johannes wuebben@math.cornell.edu
0005  * Copyright (c) 2002-2003 Aaron J. Seigo <aseigo@kde.org>
0006  * Copyright (c) 2004 Alexander Kern <alex.kern@gmx.de>
0007  * Copyright (c) 2003-2006 Richard Lärkäng <nouseforaname@home.se>
0008  *
0009  * --------------
0010  * ISI KsCD Team :
0011  * --------------
0012  * Bouchikhi Mohamed-Amine <bouchikhi.amine@gmail.com>
0013  * Gastellu Sylvain
0014  * -----------------------------------------------------------------------------
0015  *
0016  * This program is free software; you can redistribute it and/or modify
0017  * it under the terms of the GNU General Public License as published by
0018  * the Free Software Foundation; either version 2, or (at your option)
0019  * any later version.
0020  *
0021  * This program is distributed in the hope that it will be useful,
0022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0024  * GNU General Public License for more details.
0025  *
0026  * You should have received a copy of the GNU General Public License
0027  * along with this program; if not, write to the Free Software
0028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0029  *
0030  */
0031 #include "hwcontroler.h"
0032 #include "audiocd.h"
0033 #include <solid/opticaldisc.h>
0034 #include <solid/device.h>
0035 #include <solid/deviceinterface.h>
0036 #include <solid/block.h>
0037 #include <time.h>
0038 
0039 #include <kdebug.h>
0040 
0041 #include <phonon/mediasource.h>
0042 #include <phonon/mediaobject.h>
0043 #include <phonon/phononnamespace.h>
0044 #include <phonon/path.h>
0045 #include <phonon/mediacontroller.h>
0046 
0047 using namespace Phonon;
0048 
0049 HWControler::HWControler ()
0050     : selectedCd(-1)
0051     , speakers(new Phonon::AudioOutput ( MusicCategory, this ))
0052     , selectedS(-1)
0053     , media(new Phonon::MediaObject(this))
0054     , mc(new MediaController(media))
0055     , loopState(NoLoop)
0056     , random(false)
0057     , isEjectAtTheEndOfTheCdActivated(false)
0058     , posPlayList(-1)
0059 {
0060     // getting all optical disc driver
0061     QList<Solid::Device> devList = Solid::Device::listFromType(Solid::DeviceInterface::OpticalDrive, QString());
0062 
0063     // if no optical drive detected
0064     if (devList.isEmpty())
0065     {
0066         kDebug() << "No Optical Drive detected!";
0067         selectedCd = -1;
0068 
0069     }
0070 
0071     // else loading  all optical drives
0072     else
0073     {
0074         for (int i = 0; i < devList.size();i++)
0075         {
0076             cdIn.append(new AudioCD(devList[i]));
0077             selectedCd = 0;
0078             connect(cdIn[selectedCd],SIGNAL(discChanged()),this,SLOT(configMedia()));
0079         }
0080     }
0081 
0082     selectedS=0;
0083 
0084     // Multimedia configuration
0085     configMedia();
0086 }
0087 
0088 HWControler::~HWControler ()
0089 {
0090     delete speakers;
0091     delete media;
0092     delete mc;
0093 }
0094 
0095 // TODO function to switch optical drive
0096 void HWControler::selectCd(int /*cdNum*/)
0097 {
0098 
0099 }
0100 
0101 // TODO function to switch audio output
0102 void HWControler::selectSpeaker(int /*sNum*/)
0103 {
0104 
0105 }
0106 
0107 void HWControler::eject()
0108 {
0109     // if optical drive detected with a cd inside
0110     if(!(selectedCd==-1))
0111     {
0112         cdIn[selectedCd]->getCdDrive()->eject();
0113     }
0114 }
0115 
0116 void HWControler::play()
0117 {
0118     if((selectedCd!=-1))
0119     {
0120         if(cdIn[selectedCd]->isCdInserted())
0121         {
0122             /*if (!random)
0123             {*/
0124                 mc->setAutoplayTitles(true);
0125                 media->play();
0126                 kDebug() << getCurrentTrack() <<"/"<< getTotalTrack();
0127 //          }
0128             /*else
0129             {
0130                 kDebug() << "Booooooooooooooooo";
0131 
0132                 playRand();
0133             }*/
0134         }
0135         else
0136         {
0137             kDebug() << "No CD detected";
0138         }
0139     }
0140     else
0141     {
0142         kDebug() << "No Drive detected!!!";
0143     }
0144 }
0145 void HWControler::nextTrack()
0146 {
0147     if(!(selectedCd==-1))
0148     {
0149         if(cdIn[selectedCd]->isCdInserted())
0150         {
0151             if(!random)
0152             {
0153                 if(mc->currentTitle() == mc->availableTitles())
0154                 {
0155                     mc->setCurrentTitle(1);
0156                 }
0157                 else
0158                 {
0159                     mc->nextTitle();
0160                     catchCurrentTime(0);
0161                 }
0162             }
0163             else
0164             {
0165                 playRand();
0166             }
0167         }
0168     }
0169 
0170 }
0171 void HWControler::prevTrack()
0172 {
0173     if(!(selectedCd==-1))
0174     {
0175         if(cdIn[selectedCd]->isCdInserted())
0176         {
0177             if(!random)
0178             {
0179                 if(mc->currentTitle() == 1)
0180                 {
0181                     mc->setCurrentTitle(mc->availableTitles());
0182                 }
0183                 else
0184                 {
0185                     mc->previousTitle();
0186                     catchCurrentTime(0);
0187                 }
0188             }
0189             else
0190             {
0191                 playRand();
0192             }
0193         }
0194     }
0195 }
0196 void HWControler::stop(bool restart)
0197 {
0198     if(!(selectedCd==-1))
0199     {
0200         if(cdIn[selectedCd]->isCdInserted())
0201         {
0202             mc->setAutoplayTitles(false);
0203             media->stop();
0204             kDebug() << "stop with restart?" << restart;
0205             if (restart)
0206             {
0207                 mc->setCurrentTitle(1);
0208             }
0209             catchCurrentTime(0);
0210         }
0211     }
0212 }
0213 void HWControler::pause()
0214 {
0215     if(!(selectedCd==-1))
0216     {
0217         if(cdIn[selectedCd]->isCdInserted())
0218         {
0219             media->pause();
0220         }
0221     }
0222 }
0223 void HWControler::mute(bool mute)
0224 {
0225     if((selectedS!=-1))
0226     {
0227         speakers->setMuted(mute);
0228     }
0229 }
0230 
0231 qint64 HWControler::getTotalTime ()const
0232 {
0233     if(!(selectedCd==-1))
0234     {
0235         if(cdIn[selectedCd]->isCdInserted())
0236         {
0237             return media->totalTime();
0238         }
0239         else
0240         {
0241             return -1;
0242         }
0243     }
0244 
0245     else
0246     {
0247         return -1;
0248     }
0249 }
0250 qint64 HWControler::getRemainingTime ()const
0251 {
0252     if(!(selectedCd==-1))
0253     {
0254         if(cdIn[selectedCd]->isCdInserted())
0255         {
0256             return media->remainingTime();
0257         }
0258         else
0259         {
0260             return -1;
0261         }
0262     }
0263 
0264     else
0265     {
0266         return -1;
0267     }
0268 }
0269 qreal HWControler::getVolume()const
0270 {
0271     if (selectedS == -1)
0272     {
0273         return -1;
0274     }
0275     else
0276     {
0277         return speakers->volume();
0278     }
0279 }
0280 void HWControler::setVolume(qreal vol)
0281 {
0282     if (selectedS != -1)
0283     {
0284         speakers->setVolume(vol/100);
0285     }
0286 
0287 }
0288 Phonon::State HWControler ::getState()const
0289 {
0290     if(selectedCd==-1)
0291     {
0292         return ErrorState;
0293     }
0294     else
0295     {
0296         if(cdIn[selectedCd]->isCdInserted())
0297         {
0298             return media->state();
0299         }
0300         else
0301         {
0302             return ErrorState;
0303         }
0304     }
0305 }
0306 
0307 void HWControler ::configMedia()
0308 {
0309     if(selectedCd!=-1)
0310     {
0311         kDebug()<< "#o#o#o# Loading Optical Drive";
0312         if(cdIn[selectedCd]->isCdInserted())
0313         {
0314             media->setCurrentSource(*cdIn[selectedCd]->getMediaSource());
0315                         if (!path.isValid())
0316                 path = Phonon::createPath(media, speakers);
0317             kDebug()<< "Phonon Loaded";
0318             mc->setAutoplayTitles(false);
0319             media->setTickInterval(100);
0320             connect(media,SIGNAL(tick(qint64)),this,SLOT(replayTrack(qint64)));
0321             connect(media,SIGNAL(tick(qint64)),this,SLOT(catchCurrentTime(qint64)));
0322             connect(media,SIGNAL(finished()),this,SLOT(replayDisk()));
0323             connect(mc,SIGNAL(titleChanged(int)),this,SLOT(catchTitleChanged()));
0324         }
0325         emit(cdLoaded(media->currentSource().deviceName()));
0326     }
0327 }
0328 
0329 AudioCD * HWControler::getCD()const
0330 {
0331     if((selectedCd!=-1))
0332     {
0333         return cdIn[selectedCd];
0334     }
0335     return NULL;
0336 }
0337 
0338 void HWControler ::setLoopMode(LoopMode lm)
0339 {
0340     loopState = lm;
0341     kDebug()<<"Loop Mode: "<<lm;
0342 }
0343 void HWControler ::replayTrack(qint64 pos)
0344 {
0345     if(getRemainingTime()<= 500)
0346     {
0347 
0348         switch (loopState)
0349         {
0350             case LoopOne:
0351                     kDebug()<<"End of this track!";
0352                     media->stop();
0353                     mc->setCurrentTitle(mc->currentTitle());
0354                     media->play();
0355                     break;
0356             default:
0357                     if (random)
0358                     {
0359                         playRand();
0360                     }
0361         }
0362 
0363     }
0364 }
0365 void HWControler ::playRand()
0366 {
0367     bool endOfList = false;
0368     if (posPlayList == getTotalTrack() - 1)
0369     {
0370         posPlayList = 0;
0371         endOfList = true;
0372 
0373     }
0374     else
0375     {
0376         posPlayList = posPlayList + 1;
0377     }
0378     if(endOfList && loopState!=LoopAll)
0379     {
0380         stop();
0381     }
0382     else
0383     {
0384         play(playList[posPlayList]);
0385     }
0386 }
0387 
0388 void HWControler ::replayDisk()
0389 {
0390     if((selectedCd!=-1))
0391     {
0392         if(cdIn[selectedCd]->isCdInserted())
0393         {
0394             if(loopState==LoopAll)
0395             {
0396                 mc->setCurrentTitle( 1 );
0397                 play();
0398             }
0399             else{
0400                 if(isEjectAtTheEndOfTheCdActivated){
0401                     eject();
0402                  }
0403             }
0404         }
0405     }
0406 }
0407 
0408 Phonon::MediaObject * HWControler ::getMedia()const
0409 {
0410     if((selectedCd!=-1))
0411     {
0412         if(cdIn[selectedCd]->isCdInserted())
0413         {
0414             return media;
0415         }
0416     }
0417     return NULL;
0418 }
0419 void HWControler ::catchCurrentTime(qint64 pos)
0420 {
0421     emit(currentTime(pos));
0422 }
0423 Phonon::AudioOutput * HWControler ::getAudioOutPut()const
0424 {
0425     return speakers;
0426 }
0427 int HWControler ::getCurrentTrack()const
0428 {
0429     if((selectedCd!=-1))
0430     {
0431         if(cdIn[selectedCd]->isCdInserted())
0432         {
0433             return mc->currentTitle();
0434         }
0435     }
0436     return 0;
0437 }
0438 int HWControler ::getTotalTrack()const
0439 {
0440     if((selectedCd!=-1))
0441     {
0442         if(cdIn[selectedCd]->isCdInserted())
0443         {
0444             return mc->availableTitles();
0445         }
0446     }
0447     return 0;
0448 }
0449 void HWControler ::play(int track)
0450 {
0451     if((selectedCd!=-1))
0452     {
0453         if(cdIn[selectedCd]->isCdInserted())
0454         {
0455             mc->setAutoplayTitles(true);
0456             mc->setCurrentTitle(track);
0457             media->play();
0458         }
0459         else
0460         {
0461             kDebug() << "No disc inserted";
0462         }
0463     }
0464     else
0465     {
0466         kDebug() << "No drive detected";
0467     }
0468 
0469 }
0470 void HWControler ::catchTitleChanged()
0471 {
0472     emit(trackChanged());
0473 }
0474 
0475 
0476 void HWControler::setRandom(bool b)
0477 {
0478     random = b;
0479     if (b) kDebug() << "Random Activated";
0480     else   kDebug() << "Random Disabled";
0481 
0482 
0483     if((selectedCd!=-1))
0484     {
0485         if(cdIn[selectedCd]->isCdInserted())
0486         {
0487             loadPlayList();
0488         }
0489     }
0490 }
0491 
0492 
0493 bool HWControler::isDiscValid()
0494 {
0495 /*  if(getCD()->isCdInserted())
0496     {
0497         return !(getCD()->getCd()->discType()&0x01) ;
0498     }
0499     else
0500         return false;
0501 */
0502 return true;
0503 }
0504 
0505 void HWControler ::loadPlayList()
0506 {
0507     srand( time( NULL ) );
0508     int pos;
0509 
0510     posPlayList = 0;
0511 
0512     QList<int> tmp;
0513     for (int i = 0; i<getTotalTrack();i++)
0514     {
0515         tmp.append(i+1);
0516     }
0517 
0518     playList.clear();
0519 
0520     for (int i = getTotalTrack(); i>0; i--)
0521     {
0522         pos = generateNumber(i);
0523         playList.append(tmp[pos-1]);
0524         tmp.removeAt(pos-1);
0525     }
0526 
0527     for (int i = 0; i<getTotalTrack();i++)
0528     {
0529         kDebug() << "Playlist : " << playList[i];
0530     }
0531 }
0532 
0533 int HWControler ::generateNumber(int inter)
0534 {
0535     return 1 + int( double( rand() ) / ( double( RAND_MAX) + 1 ) * inter );
0536 }
0537 void HWControler ::setEjectActivated(bool b)
0538 {
0539     isEjectAtTheEndOfTheCdActivated = b;
0540     kDebug() << "Eject at the end mode changed";
0541 }
0542 
0543 bool HWControler::isEjectActivated() const
0544 {
0545     return isEjectAtTheEndOfTheCdActivated;
0546 }
0547 
0548 int HWControler::nbCdReader() const {
0549     return  cdIn.size();
0550 }
0551 
0552 QString HWControler ::getCdReader(int num)const {
0553     return cdIn[num]->signature();
0554 }