Created
March 3, 2014 05:05
-
-
Save dishbreak/9318728 to your computer and use it in GitHub Desktop.
Compiling, Coffins, and Getting to Kansas: Telling the Ends from the Means
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "brodcastmainwin.h" | |
#include "ui_brodcastmainwin.h" | |
BrodCastMainWin::BrodCastMainWin(QWidget *parent) : | |
QMainWindow(parent), | |
ui(new Ui::BrodCastMainWin) | |
{ | |
ui->setupUi(this); | |
ui->treeView->setModel(&feed); | |
stdModPoc = new StdModPoc(this, &feed); | |
stdModPoc->show(); | |
preferences = new Preferences(this, &feed); | |
//initialize the playing times | |
currentTimeString = "-:-"; | |
totalTimeString = "-:-"; | |
//create a new network manager | |
netManager = new QNetworkAccessManager(this); | |
//create a new media object | |
mediaObj = new MediaObject(this); | |
// mediaObj->setCurrentSource(Phonon::MediaSource("/Users/vishal/Dropbox/Trash80_-_03_-_Missing_You.mp3")); | |
// mediaObj->setCurrentSource(Phonon::MediaSource(QUrl("http://www.engadget.com/podcasts/Engadget_Podcast_290.mp3"))); | |
//create an audio out | |
audioOut = new AudioOutput(this); | |
//connect the two with a path. | |
Path path = Phonon::createPath(mediaObj, audioOut); | |
//pair the seek slider to the media object | |
ui->seekSlider->setMediaObject(mediaObj); | |
//pair the volume slider to the audio output | |
ui->volumeSlider->setAudioOutput(audioOut); | |
connect(ui->actionPreferences, SIGNAL(triggered()), | |
preferences, SLOT(show())); | |
connect(ui->actionOpen_File, SIGNAL(triggered()), | |
this, SLOT(openRssFile())); | |
connect(ui->treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), | |
this, SLOT(handlePodcastItem(QItemSelection,QItemSelection))); | |
// connect(ui->playPauseButton, SIGNAL(clicked()), | |
// this, SLOT(handleMediaSource())); | |
connect(mediaObj, SIGNAL(stateChanged(Phonon::State,Phonon::State)), | |
this, SLOT(handleMediaState(Phonon::State,Phonon::State))); | |
connect(ui->actionListen, SIGNAL(triggered()), | |
this, SLOT(handleMediaSource())); | |
connect(mediaObj, SIGNAL(tick(qint64)), | |
this, SLOT(handleTick(qint64))); | |
connect(mediaObj, SIGNAL(totalTimeChanged(qint64)), | |
this, SLOT(handleTotalTimeChange(qint64))); | |
connect(ui->actionFrom_URL, SIGNAL(triggered()), | |
this, SLOT(askForRssFeed())); | |
connect(preferences, SIGNAL(addButtonClicked()), | |
this, SLOT(askForRssFeed())); | |
//connect a signal so that we know when the download is finished | |
connect(netManager, SIGNAL(finished(QNetworkReply*)), | |
this, SLOT(handleNetworkReply(QNetworkReply*))); | |
} | |
BrodCastMainWin::~BrodCastMainWin() | |
{ | |
delete ui; | |
} | |
void BrodCastMainWin::requestRssFeed(QUrl rssUrl) | |
{ | |
//if the URL checks out, go ahead with the download. | |
qDebug() << "Using url" << rssUrl.toString(); | |
//grab the file | |
qDebug() << "Go for download."; | |
currentFeedUrl = rssUrl.toString(); | |
netManager->get(QNetworkRequest(rssUrl)); | |
} | |
void BrodCastMainWin::parseRssFeed(QDomDocument *xml) | |
{ | |
//set the channel node as the first child of the document element | |
QDomNode channelNode = xml->documentElement().firstChild(); | |
//begin creating the model | |
QString feedName = channelNode.toElement().namedItem("title").toElement().text(); | |
qDebug() << "Feed name" << feedName; | |
if (feedName.isEmpty()) | |
{ | |
QMessageBox::information(this, "Can't Recognize Feed", "The file you specified isn't a podcast feed. Check your link and try again."); | |
return; | |
} | |
QStandardItem *parentItem = feed.invisibleRootItem(); | |
QStandardItem *item = new QStandardItem(feedName); | |
qDebug() << feedName << "->" << currentFeedUrl; | |
item->setData(currentFeedUrl, Metadata::FeedUrl); | |
currentFeedUrl = ""; | |
item->setFlags(item->flags() & ~Qt::ItemIsEditable); | |
parentItem->appendRow(item); | |
parentItem = item; | |
//set the current node as the first child of the channel node | |
QDomNode currentNode = channelNode.firstChild(); | |
while (!currentNode.isNull()) | |
{ | |
//convert the current node to an element | |
QDomElement element = currentNode.toElement(); | |
// qDebug() << "tag:" << element.tagName() << "text:" << element.text(); | |
//check for a podcast item | |
if (element.tagName().compare("item") == 0) | |
{ | |
QString title = element.namedItem("title").toElement().text(); | |
// qDebug() << "Found episode called:" << title; | |
QStandardItem *item = new QStandardItem(title); | |
item->setFlags(item->flags() & ~Qt::ItemIsEditable); | |
//get enclosure info | |
QDomElement enclosure = element.namedItem("enclosure").toElement(); | |
item->setData(enclosure.attribute("url"), Metadata::Enclosure); | |
item->setData(enclosure.attribute("length"), Metadata::Length); | |
item->setData(enclosure.attribute("type"), Metadata::MediaType); | |
//set item unread | |
item->setData(false, Metadata::ListenedTo); | |
//set the last known seek time | |
qint64 placeHolder = 0; | |
item->setData(placeHolder, Metadata::LeftOffAt); | |
//get the description | |
item->setData(element.namedItem("description").toElement().text(), | |
Metadata::Description); | |
//get the date | |
item->setData(element.namedItem("pubDate").toElement().text(), | |
Metadata::PubDate); | |
//get the author | |
item->setData(element.namedItem("author").toElement().text(), | |
Metadata::Author); | |
//add the item to the feed | |
parentItem->appendRow(item); | |
} | |
//advance to the next sibling node. | |
currentNode = currentNode.nextSibling(); | |
} | |
qDebug() << "********TA DAAA********"; | |
delete xml; | |
} | |
QString BrodCastMainWin::convertTime(qint64 inputTime) | |
{ | |
//bring the ms time into a QTime object | |
QTime playTime((inputTime/3600000) % 60, (inputTime/60000) % 60, (inputTime/1000) % 60); | |
//spit out the time in a readable string | |
if (playTime.hour() > 0) | |
{ | |
//if the play time is longer than an hour, display this way. | |
return playTime.toString("h:mm:ss"); | |
} | |
else | |
{ | |
//if it isn't, display this way | |
return playTime.toString("mm:ss"); | |
} | |
} | |
void BrodCastMainWin::keyPressEvent(QKeyEvent *e) | |
{ | |
qDebug() << "Key Pressed is:" << e->key(); | |
if (e->key() == Qt::Key_F8) | |
{ | |
qDebug() << "Got the right key!"; | |
ui->playPauseButton->animateClick(); | |
} | |
} | |
/***************** | |
***SLOTS******** | |
***************/ | |
void BrodCastMainWin::handleMediaState(Phonon::State state, Phonon::State) | |
{ | |
switch (state) | |
{ | |
case Phonon::PlayingState: | |
qDebug() << "Playing/Loading/Buffering; switching button to 'pause'"; | |
//If we're playing, the button should pause | |
ui->playPauseButton->setIcon(QIcon(":/assets/stock_media-pause.svg")); | |
connect(ui->playPauseButton, SIGNAL(clicked()), | |
this, SLOT(pauseStream())); | |
break; | |
case Phonon::PausedState: | |
qDebug() << "switching button to 'play'"; | |
//if we're paused, the button should play | |
ui->playPauseButton->setIcon(QIcon(":/assets/stock_media-play.svg")); | |
connect(ui->playPauseButton, SIGNAL(clicked()), | |
this, SLOT(playStream())); | |
break; | |
case Phonon::ErrorState: | |
//additionally, if there's an error, do error handling. | |
break; | |
case Phonon::LoadingState: | |
case Phonon::BufferingState: | |
case Phonon::StoppedState: | |
default: | |
break; | |
} | |
} | |
void BrodCastMainWin::openRssFile() | |
{ | |
//this code manually opens an arbitrary file. | |
//in the future, we'll grab files from the internet. | |
QString xmlFile = QFileDialog::getOpenFileName(this,"Open XML File", | |
QDir::currentPath(), | |
"XML (*.xml)"); | |
qDebug() << "File name is:" << xmlFile; | |
file = new QFile(xmlFile); | |
//if the file exists... | |
if (file->exists()) | |
{ | |
//...open it. | |
qDebug() << "Opening file"; | |
file->open(QIODevice::ReadOnly); | |
QDomDocument *xml = new QDomDocument("Local_File"); | |
xml->setContent(file); | |
qDebug() << "Calling parser"; | |
parseRssFeed(xml); | |
} | |
//close the file and put it away. | |
file->close(); | |
delete file; | |
//delete the xml | |
} | |
void BrodCastMainWin::askForRssFeed() | |
{ | |
//prompt the user for a url | |
QString userUrl = QInputDialog::getText(this, "Enter Feed URL", "Enter the URL of the podcast feed"); | |
// | |
QUrl rssUrl = QUrl::fromUserInput(userUrl); | |
qDebug() << "rssUrl.toString:" << rssUrl.toString(); | |
qDebug() << "rssUrl.host:" << rssUrl.host(); | |
qDebug() << "rssUrl.path" << rssUrl.path(); | |
qDebug() << "userUrl" << userUrl; | |
if(!rssUrl.toString().isEmpty() && | |
!rssUrl.host().isEmpty() && | |
!rssUrl.path().isEmpty()) | |
{ | |
requestRssFeed(rssUrl); | |
} | |
else if (!userUrl.isEmpty()) | |
{ | |
QMessageBox::information(this, "Invalid URL!", | |
"BrodCast doesn't recognize that as a valid RSS URL. Check the address and try again."); | |
askForRssFeed(); | |
} | |
} | |
void BrodCastMainWin::handlePodcastItem(QItemSelection selected, QItemSelection deselected) | |
{ | |
//we don't need this, so get rid of it. | |
deselected.clear(); | |
//open up the QList inside selected.indexes | |
for (int i = 0; i < selected.indexes().size(); i++) | |
{//each entry in this list corresponds to a selected item in the view | |
clickedItem = selected.indexes().at(i); | |
qDebug() << "******" ; | |
qDebug() << "Selected:" << clickedItem.data(Qt::DisplayRole).toString(); | |
qDebug() << "field:" << clickedItem.data(Metadata::Author); | |
//render the description in the web view | |
ui->webView->setHtml(clickedItem.data(Metadata::Description).toString()); | |
} | |
} | |
void BrodCastMainWin::handleMediaSource() | |
{ | |
//set the media source to the selected stream | |
mediaObj->setCurrentSource(Phonon::MediaSource( | |
QUrl(clickedItem.data(Metadata::Enclosure).toString()))); | |
//set the now playing to the episode title | |
ui->episodeLabel->setText(clickedItem.data(Qt::DisplayRole).toString()); | |
//set the now playing index to the current index | |
nowPlaying = clickedItem; | |
//start playing the episode | |
playStream(); | |
} | |
void BrodCastMainWin::handleTick(qint64 newTime) | |
{ | |
//update the current time | |
currentTime = newTime; | |
//turn the new time data into something human readable | |
currentTimeString = convertTime(newTime); | |
//update the label | |
ui->timeLabel->setText(currentTimeString + " / " + totalTimeString); | |
} | |
void BrodCastMainWin::handleTotalTimeChange(qint64 newTime) | |
{ | |
//update the total time | |
totalTimeString = convertTime(newTime); | |
//turn the total time into something human readable | |
ui->timeLabel->setText(currentTimeString + " / " + totalTimeString); | |
} | |
void BrodCastMainWin::pauseStream() | |
{ | |
//save the "left off at" point in the stream | |
qDebug() << "current time is:" << currentTime; | |
qDebug() << "Saving place at" << currentTimeString | |
<< "in item" << nowPlaying.data(Qt::DisplayRole).toString(); | |
//need to use QModelIndex for setData() | |
QModelIndex nowPlayingHandle = nowPlaying; | |
feed.setData(nowPlayingHandle, QVariant(currentTime), Metadata::LeftOffAt); | |
//pause the stream | |
mediaObj->pause(); | |
} | |
void BrodCastMainWin::playStream() | |
{ | |
//seek to the "left off at" point in the stream | |
qDebug() << "Trying to seek to" << convertTime(nowPlaying.data(Metadata::LeftOffAt).toLongLong()) | |
<< "in item" << nowPlaying.data(Qt::DisplayRole).toString(); | |
mediaObj->seek(nowPlaying.data(Metadata::LeftOffAt).toLongLong()); | |
//play the file | |
mediaObj->play(); | |
} | |
void BrodCastMainWin::handleNetworkReply(QNetworkReply *reply) | |
{ | |
disconnect(); | |
qDebug() << "download is complete!"; | |
QDomDocument *xml = new QDomDocument("Web_File"); | |
xml->setContent(reply->readAll()); | |
parseRssFeed(xml); | |
//delete xml; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment