Skip to content

Instantly share code, notes, and snippets.

@dishbreak
Created March 3, 2014 05:05
Show Gist options
  • Save dishbreak/9318728 to your computer and use it in GitHub Desktop.
Save dishbreak/9318728 to your computer and use it in GitHub Desktop.
Compiling, Coffins, and Getting to Kansas: Telling the Ends from the Means
#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