/** Add a track and set it as current item */ void Playlist::addCurrentTrack( Track* track ) { //Add if it comes from outsite only bool fromOutsite=true; PlaylistItem* currItem = (PlaylistItem*)currentItem(); if ( currItem ) if ( track->url() == currItem->track()->url() ) fromOutsite=false; if ( fromOutsite ) addTrack(track,NULL); else newPlaylistItem = currItem; if (!m_isPlaying){ //is not playing, direct into player and roll others setCurrentPlaylistItem( newPlaylistItem ); } else { //is playing, wait and add as next setNextPlaylistItem( newPlaylistItem ); } handleChanges(); }
void SourceTreeView::addToLocal() { QModelIndex idx = m_contextMenuIndex; if ( !idx.isValid() ) return; SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt(); if( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( m_contextMenuIndex ); dynplaylist_ptr playlist = item->dynPlaylist(); // copy to a link and then generate a new playlist from that // this way we cheaply regenerate the needed controls QString link = GlobalActionManager::instance()->copyPlaylistToClipboard( playlist ); GlobalActionManager::instance()->parseTomahawkLink( link ); } else if ( type == SourcesModel::StaticPlaylist ) { PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); playlist_ptr playlist = item->playlist(); // just create the new playlist with the same values QList< query_ptr > queries; foreach( const plentry_ptr& e, playlist->entries() ) queries << e->query(); playlist_ptr newpl = Playlist::create( SourceList::instance()->getLocal(), uuid(), playlist->title(), playlist->info(), playlist->creator(), playlist->shared(), queries ); }
bool PlaylistSaver::saveM3U(const KURL &file, int opt) { // kdDebug(66666) << k_funcinfo << "file='" << file.path() << "', opt=" << opt << endl; bool isExt=(opt==EXTM3U); // easier ;) QString local(napp->tempSaveName(file.path())); QFile saver(local); saver.open(IO_ReadWrite | IO_Truncate); QTextStream t(&saver); reset(); PlaylistItem i; QStringList props; // this is more code but otoh faster than checking for isExt inside the loop if(isExt) { t << "#EXTM3U" << '\n'; while ((i=writeItem())) { int length = static_cast<int>(((i.property("length")).toInt())/1000); if(length==0) length=-1; // special value in an EXTM3U file, means "unknown" KURL u(i.property("url")); QString title; // if a playlistitem is without a tag or ONLY title is set if((i.property("author").isEmpty() && i.property("title").isEmpty()) || (i.property("author").isEmpty() && !i.property("title").isEmpty()) ) title = u.filename().left(u.filename().length()-4); else title = i.property("author") + " - " + i.property("title"); // kdDebug(66666) << "#EXTINF:"<< QString::number(length) << "," << title << endl; t << "#EXTINF:"<< QString::number(length) << "," << title << '\n'; if (u.isLocalFile()) t << u.path() << '\n'; else t << u.url() << '\n'; } } else { while ((i=writeItem())) { KURL u(i.property("url")); if (u.isLocalFile()) t << u.path() << '\n'; else t << u.url() << '\n'; } } saver.close(); KIO::NetAccess::upload(local, file, 0L); saver.remove(); return true; }
CopyPLItemsCommand::CopyPLItemsCommand(Playlist* playlist, const int32* indices, int32 count, int32 toIndex) : PLItemsCommand(), fPlaylist(playlist), fItems(count > 0 ? new (nothrow) PlaylistItem*[count] : NULL), fToIndex(toIndex), fCount(count), fItemsCopied(false) { if (!indices || !fPlaylist || !fItems) { // indicate a bad object state delete[] fItems; fItems = NULL; return; } memset(fItems, 0, sizeof(PlaylistItem*) * fCount); // init original entries and for (int32 i = 0; i < fCount; i++) { PlaylistItem* item = fPlaylist->ItemAt(indices[i]); if (item != NULL) fItems[i] = item->Clone(); if (fItems[i] == NULL) { // indicate a bad object state _CleanUp(fItems, fCount, true); return; } } }
bool PlaylistsModel::load() { setUpdateSignaled(false); if (!m_provider) return false; clear(); const SONOS::PlayerPtr player = m_provider->getPlayer(); if (!player) return false; QString port; port.setNum(player->GetPort()); QString url = "http://"; url.append(player->GetHost().c_str()).append(":").append(port); SONOS::ContentDirectory cd(player->GetHost(), player->GetPort()); SONOS::ContentList cl(cd, m_root.isEmpty() ? SONOS::ContentSearch(SONOS::SearchSonosPlaylist,"").Root() : m_root.toUtf8().constData()); for (SONOS::ContentList::iterator it = cl.begin(); it != cl.end(); ++it) { PlaylistItem* item = new PlaylistItem(*it, url); if (item->isValid()) addItem(item); else delete item; } if (cl.failure()) return m_loaded = false; m_updateID = cl.GetUpdateID(); // sync new baseline return m_loaded = true; }
void SourceTreeView::copyPlaylistLink() { QModelIndex idx = m_contextMenuIndex; if ( !idx.isValid() ) return; SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt(); if( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( m_contextMenuIndex ); dynplaylist_ptr playlist = item->dynPlaylist(); GlobalActionManager::instance()->copyPlaylistToClipboard( playlist ); } else if ( type == SourcesModel::StaticPlaylist ) { PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex ); playlist_ptr playlist = item->playlist(); QString suggestedFilename = TomahawkSettings::instance()->playlistDefaultPath() + "/" + playlist->title(); QString filename = QFileDialog::getSaveFileName( TomahawkUtils::tomahawkWindow(), tr( "Save XSPF" ), suggestedFilename, tr( "Playlists (*.xspf)" ) ); if ( !filename.isEmpty() ) { QFileInfo playlistAbsoluteFilePath = filename; TomahawkSettings::instance()->setPlaylistDefaultPath( playlistAbsoluteFilePath.absolutePath() ); GlobalActionManager::instance()->savePlaylistToFile( playlist, filename ); } } }
void PLSimport::readFile() { QFile file(filename); if (!file.open(QFile::ReadOnly)) { return; } QTextStream is(&file); PlaylistItem* p; // QString* duration; // QString* title; QString* uri; QRegExp rxlen("="); QRegExp rxlen2("(\\d+)"); int pos=-1; is.readLine(); int i = rxlen2.indexIn(is.readLine()); if(i>-1) i = rxlen2.cap(1).toInt(); is.readLine(); for(int j = 0 ;j<i;j++) { p= new PlaylistItem; uri = new QString; *uri = is.readLine(); pos = rxlen.indexIn(*uri); if (pos > -1) { uri->remove(0, pos+1); } is.readLine(); is.readLine(); is.readLine(); p->setURI(*uri); result->append(p); } }
void Playlist::MakeEmpty(bool deleteItems) { int32 count = CountItems(); for (int32 i = count - 1; i >= 0; i--) { PlaylistItem* item = RemoveItem(i, false); _NotifyItemRemoved(i); if (deleteItems) item->ReleaseReference(); } SetCurrentItemIndex(-1); }
void Playlist::addTrack( Track* track, PlaylistItem* after ) { if (!track || !track->isValid()) return; //qDebug() << __PRETTY_FUNCTION__ <<":"<<objectName()<<" url="<<track->url(); PlaylistItem* item = new PlaylistItem( this, after ); item->setTexts( track ); newPlaylistItem = item; RatingWidget* rating= new RatingWidget(); rating->setRating( track->rate() * 0.1 ); QObject::connect(rating,SIGNAL(RatingChanged(float)),SLOT(onRatingChanged(float))); setItemWidget(item, PlaylistItem::Column_Rate, rating); }
/** Updates the playlist listbox. * */ void PlaylistFrame::UpdatePlaylist() { //Clear playlist m_lstBoxPlaylist->Clear(); m_lstBoxPlaylist->SetForegroundColour(wxColour(0,255,0)); PlaylistItem item; std::list<PlaylistItem>::const_iterator it; for(it = m_playlist.Begin(); it != m_playlist.End(); it++) { item = *it; m_lstBoxPlaylist->Append(item.GetFilename()); } }
/** Begin play a movie in the playlist. * Private method. */ void PlaylistFrame::BeginPlayFile() { if (m_itemPlaying < m_playlist.GetSize()) { const Channel *channel = m_appInterface->GetCurrentChannel(); //Get channel bitrate Mode mode; ModeList modeList = channel->GetModeList(); modeList.FindMode(IRM_MODE_CHANNEL_BITRATE, mode); long bitrate; mode.GetParameter().ToLong(&bitrate); PlaylistItem item; std::list<PlaylistItem>::const_iterator it; it = m_playlist.Begin(); for(int i = 0;i<m_itemPlaying;i++) it++; item = *it; bool ret = m_appInterface->MovieBeginTransmission(channel->GetName(), item.GetPath(), bitrate); SetFieldsStates(ret); m_lstBoxPlaylist->SetSelection(m_itemPlaying); SetStatusText(wxString::Format(_("Playing file: %s"), item.GetFilename().c_str())); if (!ret) { wxString msg = wxString::Format(_("Error while attempt play %s"), item.GetFilename().c_str()); wxMessageBox(msg, wxMessageBoxCaptionStr, wxOK|wxICON_ERROR, this); } } else { if (m_chkBoxRepeat->IsChecked()) { m_itemPlaying = 0; BeginPlayFile(); } else { wxString msg = _("Finished send transmission of Playlist"); wxMessageBox(msg, _("Information"), wxICON_INFORMATION|wxOK, this); m_appInterface->MovieCancelTransmission(m_mediaId); SetFieldsStates(false); SetStatusText(wxEmptyString); } } }
bool PlaylistSaver::saveXML(const KURL &file, int ) { QString localFile; if (file.isLocalFile()) localFile = QFile::encodeName(file.path()); else localFile = napp->tempSaveName(file.path()); // QDom is a pain :) QDomDocument doc("playlist"); doc.setContent(QString("<!DOCTYPE XMLPlaylist><playlist version=\"1.0\" client=\"noatun\"/>")); QDomElement docElem=doc.documentElement(); reset(); PlaylistItem i; QStringList props; while ((i=writeItem())) { // write all properties props=i.properties(); QDomElement elem=doc.createElement("item"); for (QStringList::Iterator pi(props.begin()); pi!=props.end(); ++pi) { QString val=i.property(*pi); elem.setAttribute(*pi, val); if ((*pi)=="url") { KURL u(val); if (u.isLocalFile()) { elem.setAttribute("local", u.path()); } } } docElem.appendChild(elem); props.clear(); } Noatun::KSaver saver(localFile); if (!saver.open()) return false; saver.textStream().setEncoding(QTextStream::UnicodeUTF8); saver.textStream() << doc.toString(); saver.close(); return true; }
void QueueManager::insertItems() { QPtrList<PlaylistItem> list = Playlist::instance()->m_nextTracks; QListViewItem *last = 0; for( PlaylistItem *item = list.first(); item; item = list.next() ) { QString title = i18n("%1 - %2").arg( item->artist(), item->title() ); last = new QueueItem( m_listview, last, title ); m_map[ last ] = item; } updateButtons(); }
void Playlist::addItems(const PlaylistItem &item) { QVariantMap params; params.insert("item", item.toMap()); params.insert("playlistid", playlistId()); KodiConnection::sendCommand("Playlist.Add", params); refresh(); }
QVariantMap MediaPlayer2Player::Metadata() const { QVariantMap metaData; // The track ID is annoying since it must result in a valid DBus object // path, and the regex for that is, and I quote: [a-zA-Z0-9_]*, along with // the normal / delimiters for paths. PlaylistItem *item = Playlist::playingItem(); if (!item) return metaData; FileHandle playingFile = item->file(); QByteArray playingTrackFileId = idFromPlaylistItem(item); metaData["mpris:trackid"] = QVariant::fromValue<QDBusObjectPath>( QDBusObjectPath(playingTrackFileId.constData())); metaData["xesam:album"] = playingFile.tag()->album(); metaData["xesam:title"] = playingFile.tag()->title(); metaData["xesam:artist"] = QStringList(playingFile.tag()->artist()); metaData["xesam:genre"] = QStringList(playingFile.tag()->genre()); metaData["mpris:length"] = qint64(playingFile.tag()->seconds() * 1000000); metaData["xesam:url"] = QString::fromLatin1( KUrl::fromLocalFile(playingFile.absFilePath()).toEncoded()); if(playingFile.coverInfo()->hasCover()) { QString fallbackFileName = KStandardDirs::locateLocal("tmp", QString("juk-cover-%1.png").arg(item->trackId())); QString path = fallbackFileName; if(!QFile::exists(path)) { path = playingFile.coverInfo()->localPathToCover(fallbackFileName); } metaData["mpris:artUrl"] = QString::fromLatin1(QUrl::fromLocalFile( path).toEncoded()); } return metaData; }
static void import_tool(GtkWidget *w, GTKMusicBrowser *p) { FileSelector *filesel = new FileSelector(p->GetContext(),"Import a Track or Playlist into My Music"); if (filesel->Run()) { FAContext *m_context = p->GetContext(); char *returnpath = filesel->GetReturnPath(); char *filereturn = strdup_new(returnpath); if (filereturn) { char *first = strtok(filereturn, "\n"); while (first) { char *ext = m_context->player->GetExtension(first); uint32 length = strlen(first) + 10; char *tempurl = new char[length]; if (IsntError(FilePathToURL(first, tempurl, &length))) { if (ext && m_context->plm->IsSupportedPlaylistFormat(ext)) p->ImportPlaylist(tempurl); else if (ext && m_context->player->IsSupportedExtension(ext)) { PlaylistItem *plist = new PlaylistItem(tempurl); m_context->plm->RetrieveMetaDataNow(plist); m_context->catalog->WriteMetaDataToDatabase(tempurl, plist->GetMetaData()); m_context->catalog->AddSong(tempurl); delete plist; } } delete [] tempurl; delete ext; first = strtok(NULL, "\n"); } delete [] filereturn; } } delete filesel; }
QByteArray Playlist::toPLS(const QString& playlistPath, const bool utf8) const { QStringList playlist; playlist.append("[Playlist]"); int j = 0; for (int i = 0; i < p_playlist.count(); ++i) { PlaylistItem pi = p_playlist[i]; if (pi.filename().isEmpty()) continue; ++j; if (!playlistPath.isEmpty()) { QDir dir(playlistPath); playlist.append(QString("File%1=%2").arg(i+1).arg(dir.relativeFilePath(pi.filename()))); } else { playlist.append(QString("File%1=%2").arg(i+1).arg(pi.filename())); } if (!pi.artist().isEmpty()) { playlist.append(QString("Title%1=%2 - %3").arg(i+1).arg(pi.artist()).arg(pi.title())); } else { playlist.append(QString("Title%1=%2").arg(i+1).arg(pi.title())); } playlist.append(QString("Length%1=%2").arg(i+1).arg(pi.length())); } playlist.append(QString("NumberOfEntries=%1").arg(j)); playlist.append(QString("Version=2")); if (utf8) return playlist.join("\n").append("\n").toUtf8(); else return playlist.join("\n").append("\n").toLatin1(); }
PlaylistItem *CollectionList::createItem(const FileHandle &file, QListViewItem *, bool) { // It's probably possible to optimize the line below away, but, well, right // now it's more important to not load duplicate items. if(m_itemsDict.find(file.absFilePath())) return 0; PlaylistItem *item = new CollectionListItem(file); if(!item->isValid()) { kdError() << "CollectionList::createItem() -- A valid tag was not created for \"" << file.absFilePath() << "\"" << endl; delete item; return 0; } setupItem(item); return item; }
/** Save playlist to file. * Private method. Return true if file was saved or false if occurs a error. */ bool PlaylistFrame::SavePlaylist() { //If don�t have playlist, don�t create file if (m_playlist.GetSize() == 0) return false; wxString wildcard = _("Playlist|*.ivl"); wxFileDialog fileDlg(this, wxFileSelectorPromptStr, wxEmptyString, wxEmptyString, wildcard, wxFD_SAVE); if (fileDlg.ShowModal() == wxID_OK) { wxString filePath = fileDlg.GetPath(); if (wxFile::Access(filePath, wxFile::write)) { MessageDialog msgDlg(this, _("Confirm"), _("Overwite file?")); if ( msgDlg.ShowModal() == ID_MESSAGEDIALOG_BTN_NO) return false; } #ifdef __WXGTK__ filePath += wxT(".ivl"); ofstream playlistFile(WX_TO_FILE_CSTR(filePath)); #else ofstream playlistFile(WX_TO_FILE_CSTR(filePath)); #endif PlaylistItem item; std::list<PlaylistItem>::iterator it; for(it = m_playlist.Begin(); it != m_playlist.End(); it++) { item = *it; playlistFile << WX_TO_FILE_CSTR(item.GetPath()) << "\n"; } playlistFile.close(); wxMessageBox(_("Playlist saved successfully."), _("Information"), wxOK, this); } return true; }
void Playlist::p_add_M3U(const QByteArray& playlist) { QTextStream stream(playlist, QIODevice::ReadOnly); QString line = stream.readLine().trimmed(); bool extended = false; if (line.startsWith("#EXTM3U")) { extended = true; line = stream.readLine().trimmed(); } PlaylistItem pi; while (!line.isNull()) { if (line.startsWith('#')) { if (extended && line.startsWith("#EXT")) { pi = p_parse_m3u_metadata_line(line); } } else if (!line.isEmpty()) { pi.setFilename(line); if (!pi.filename().isEmpty()) { p_playlist.append(pi); pi.clear(); } } line = stream.readLine().trimmed(); } }
void PlaylistWindow::savePlaylist() const //SLOT { Playlist *pl = Playlist::instance(); PlaylistItem *item = pl->firstChild(); if( item && !item->isVisible() ) item = static_cast<PlaylistItem*>( item->itemBelow() ); QString title = i18n( "Untitled" ); if( item ) { QString artist = item->artist(); QString album = item->album(); bool useArtist = true, useAlbum = true; item = static_cast<PlaylistItem*>( item->itemBelow() ); for( ; item; item = static_cast<PlaylistItem*>( item->itemBelow() ) ) { if( artist != item->artist() ) useArtist = false; if( album != item->album() ) useAlbum = false; if( !useArtist && !useAlbum ) break; } if( useArtist && useAlbum ) title = i18n("%1 - %2").arg( artist, album ); else if( useArtist ) title = artist; else if( useAlbum ) title = album; } QString path = PlaylistDialog::getSaveFileName( title ); if( !path.isEmpty() && Playlist::instance()->saveM3U( path ) ) PlaylistWindow::self()->showBrowser( "PlaylistBrowser" ); }
void SourceTreeView::deletePlaylist( const QModelIndex& idxIn ) { qDebug() << Q_FUNC_INFO; QModelIndex idx = idxIn.isValid() ? idxIn : m_contextMenuIndex; if ( !idx.isValid() ) return; SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( idx, SourcesModel::SourceTreeItemTypeRole ).toInt(); if ( type == SourcesModel::StaticPlaylist ) { PlaylistItem* item = itemFromIndex< PlaylistItem >( idx ); playlist_ptr playlist = item->playlist(); Playlist::remove( playlist ); } else if( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station ) { DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( idx ); dynplaylist_ptr playlist = item->dynPlaylist(); DynamicPlaylist::remove( playlist ); } }
void YoutubeProtocolHandler::execute(const QUrl &uri, bool queue) { QStringList parts = uri.path().split('/'); QUrlQuery query; if (parts.count()) { query.addQueryItem("action", "play_video"); query.addQueryItem("videoid", parts.last()); } if (query.isEmpty()) { return; } PlaylistItem item; item.setFile("plugin://plugin.video.youtube/?" + query.toString()); Player *player = Kodi::instance()->videoPlayer(); if (queue) { player->playlist()->addItems(item); } else { player->open(item); } }
const PlaylistItem Playlist::p_parse_m3u_metadata_line(const QString& line) { PlaylistItem pi; QString info = line.section(':', 1); QString l = info.section(',', 0, 0); bool ok; int length = l.toInt(&ok); if (!ok) return pi; pi.setLength(length); QString track_info = info.section(',', 1); QStringList list = track_info.split('-'); if (list.length() <= 1) { pi.setTitle(track_info); return pi; } pi.setArtist(list[0].trimmed()); pi.setTitle(list[1].trimmed()); return pi; }
void play() { currentPlaylistItem = playlist_.current(); if (currentPlaylistItem.empty()) { BOOST_LOG_TRIVIAL(debug) << "Playlist is currently empty, or we reached its end."; return; } for (;;) { if (play(currentPlaylistItem.uri_)) break; // no need to update status now. it'll get updated when client will ask for // it // if the item could not be played, then automatically continue with next // item BOOST_LOG_TRIVIAL(debug) << "Trying next item in the playlist"; currentPlaylistItem = playlist_.next(); if (currentPlaylistItem.empty()) { BOOST_LOG_TRIVIAL(debug) << "Playlist is currently empty, or we reached its end."; return; } } }
QByteArray Playlist::toM3U(const QString& playlistPath, const bool utf8) const { QStringList playlist; playlist.append("#EXTM3U"); for (int i = 0; i < p_playlist.count(); ++i) { PlaylistItem pi = p_playlist[i]; if (pi.filename().isEmpty()) continue; if (!pi.artist().isEmpty()) { playlist.append(QString("#EXTINF:%1,%2 - %3").arg(pi.length()).arg(pi.artist()).arg(pi.title())); } else { playlist.append(QString("#EXTINF:%1,%2").arg(pi.length()).arg(pi.title())); } if (!playlistPath.isEmpty()) { QDir dir(playlistPath); playlist.append(dir.relativeFilePath(pi.filename())); } else { playlist.append(pi.filename()); } } if (utf8) return playlist.join("\n").append("\n").toUtf8(); else return playlist.join("\n").append("\n").toLatin1(); }
QByteArray Playlist::toXSPF() const { QDomDocument doc; QDomElement root = doc.createElement("playlist"); root.setAttribute("version", "1"); root.setAttribute("xmlns", "http://xspf.org/ns/0"); QDomElement creator = doc.createElement("creator"); QDomText text = doc.createTextNode("audex"); creator.appendChild(text); root.appendChild(creator); QDomElement tracklist = doc.createElement("trackList"); int j = 0; for (int i = 0; i < p_playlist.count(); ++i) { PlaylistItem pi = p_playlist[i]; if (pi.filename().isEmpty()) continue; ++j; QDomElement track = doc.createElement("track"); QDomElement ch = doc.createElement("location"); QDomText text = doc.createTextNode(pi.filename()); ch.appendChild(text); track.appendChild(ch); if (!pi.artist().isEmpty()) { ch = doc.createElement("creator"); text = doc.createTextNode(pi.artist()); ch.appendChild(text); track.appendChild(ch); } ch = doc.createElement("title"); text = doc.createTextNode(pi.title()); ch.appendChild(text); track.appendChild(ch); ch = doc.createElement("trackNum"); text = doc.createTextNode(QString::number(j)); ch.appendChild(text); track.appendChild(ch); if (pi.length() > 0) { ch = doc.createElement("duration"); text = doc.createTextNode(QString::number(pi.length()*1000)); ch.appendChild(text); track.appendChild(ch); } tracklist.appendChild(track); } root.appendChild(tracklist); doc.appendChild(root); QByteArray xml_header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); return doc.toByteArray().prepend(xml_header); }
void VorbisLMC::DecodeWork() { void *pOutBuffer; Error Err; int32 iValue; int32 section, ret; OutputInfo *info; vorbis_info *vi; uint32 bytesCopied, bytesPerFrame; int bitrateLoops = 0; assert(m_pPmi); assert(m_pPmo); m_pSleepSem->Wait(); m_pPmi->Wake(); Err = CanDecode(); if (Err == kError_Interrupt) return; if (Err != kError_NoErr) { m_pContext->log->Error("CanDecode returned false.\n"); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } Err = ExtractMediaInfo(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("ExtractMediaInfo failed: %d\n", Err); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } if (!m_bInit) { Err = InitDecoder(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("Initializing the decoder failed: %d\n", Err); ReportError("Initializing the decoder failed."); return; } } m_pContext->prefs->GetPrefInt32(kDecoderThreadPriorityPref, &iValue); m_decoderThread->SetPriority(iValue); bytesCopied = 0; bytesPerFrame = 1; for (m_frameCounter = 0; !m_bExit;) { if (m_bPause) { m_pPauseSem->Wait(); if (m_bExit) break; } if (m_newPos >= 0) { ov_time_seek(&m_vf, (double)(m_newPos / iFramesPerSecond)); m_frameCounter = m_newPos - 1; m_newPos = -1; bytesCopied = bytesPerFrame; } if (bytesCopied >= bytesPerFrame) { m_frameCounter += bytesCopied / bytesPerFrame; bytesCopied %= bytesPerFrame; ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); bitrateLoops++; if (bitrateLoops == iBitrateLoopsPerUpdate && m_decodeInfo.sendInfo) { int b; b = ov_bitrate_instant(&m_vf), vi = ov_info(&m_vf, -1); VorbisInfoEvent *mie = new VorbisInfoEvent(b, vi->channels, vi->rate, 1. / (float)iFramesPerSecond); m_pTarget->AcceptEvent(mie); bitrateLoops = 0; } } Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err == kError_Interrupt) { break; } if (Err == kError_BufferTooSmall) { if (Sleep()) break; continue; } if (Err != kError_NoErr) { ReportError(szFailWrite); m_pContext->log->Error("LMC: Cannot write to eventbuffer: %s (%d)\n", m_szError, Err); break; } section = -1; ret = ov_read(&m_vf, (char *)pOutBuffer, iDecodeBlockSize, 0, 2, 1, §ion); if (ret == 0) { m_pOutputBuffer->EndWrite(0); break; } if (section != m_section) { vi = ov_info(&m_vf, -1); info = new OutputInfo; info->bits_per_sample = 16; info->number_of_channels = m_channels = vi->channels; info->samples_per_second = m_rate = vi->rate; info->samples_per_frame = vi->rate / iFramesPerSecond; info->max_buffer_size = 16384; m_frameCounter = 0; bytesCopied = 0; bytesPerFrame = (vi->rate / iFramesPerSecond) * sizeof(ogg_int16_t) * vi->channels; m_section = section; m_pOutputBuffer->EndWrite(0); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOInitEvent(info)); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err != kError_NoErr) { assert(0); } vorbis_comment *comment; comment = ov_comment(&m_vf, -1); if (comment) { PlaylistItem *plItem = m_pContext->plm->GetCurrentItem(); if (plItem) { MetaData mdata = plItem->GetMetaData(); string iso; char *temp; temp = vorbis_comment_query(comment, "title", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetTitle(iso); } temp = vorbis_comment_query(comment, "artist", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetArtist(iso); } temp = vorbis_comment_query(comment, "album", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetAlbum(iso); } temp = vorbis_comment_query(comment, "tracknumber", 0); if (temp) mdata.SetTrack(atoi(temp)); plItem->SetMetaData(&mdata); m_pContext->target->AcceptEvent( new PlaylistCurrentItemInfoEvent(plItem, m_pContext->plm)); } } } if(ret <0) ret=0; // hole/error in data - we can safely ignore this m_pOutputBuffer->EndWrite(ret); bytesCopied += ret; } ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent()); ov_clear(&m_vf); return; }
Error PMP300::WritePlaylist(DeviceInfo* device, vector<PlaylistItem*>* list, PLMCallBackFunction function, void* cookie) { Error result = kError_InvalidParam; assert(device); assert(list); if(device && list) { result = kError_DeviceNotFound; if(!strcasecmp(device->GetDevice(), devices[0].device)) { CRio rioInternal, rioExternal; bool rioPresent = false; rioPresent = FindRio(rioInternal, device, function, cookie); if(rioPresent) { FindRio(rioExternal, device, function, cookie); rioExternal.UseExternalFlash(true); if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString += "A "; event.eventString = device->GetDevice(); event.eventString += " has been found. Scanning internal memory..."; function(&event, cookie); } vector<PlaylistItem*> origInternal; vector<PlaylistItem*> origExternal; vector<PlaylistItem*> newInternal; vector<PlaylistItem*> newExternal; uint32 externalTotal = 0, internalTotal = 0, usedMem; uint32 count, index; char* path = new char[_MAX_PATH]; char* tempPath = new char[_MAX_PATH]; uint32 length = _MAX_PATH; // get a temp path m_context->prefs->GetPrefString(kInstallDirPref, tempPath, &length); strcat(tempPath, tmpnam(NULL)); #ifdef WIN32 mkdir(tempPath); #else mkdir(tempPath, S_IRWXU); #endif // first get current state of device // we break our lists into internal and // external lists for ease of organizing result = privateReadPlaylist(rioInternal, false, &internalTotal, &usedMem, &origInternal, function, cookie); if(IsntError(result)) { if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString = "Scanning external memory..."; function(&event, cookie); } privateReadPlaylist(rioExternal, true, &externalTotal, &usedMem, &origExternal, function, cookie); } count = list->size(); bool useExternal = false; for(index = 0; index < count; index++) { PlaylistItem* item = (*list)[index]; if(item) { MetaData metadata = item->GetMetaData(); int32 size = metadata.Size(); if(!size) { struct stat st; length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); if(!stat(path, &st)) size = st.st_size; else { result = kError_FileNoAccess; break; } } // figure out where to put it... uint32* memorySize; vector<PlaylistItem*>* addList; if(!useExternal) { memorySize = &internalTotal; addList = &newInternal; if(*memorySize < (uint32)size) useExternal = true; else *memorySize -= size; } if(useExternal) { memorySize = &externalTotal; addList = &newExternal; if(*memorySize < (uint32)size) break; else *memorySize -= size; } addList->push_back(item); } } // if all is well we delete old files // and temporarily download files // that are being moved from internal // to external and vice versa... if(IsntError(result)) { if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString = "Deleting files..."; function(&event, cookie); } count = origInternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origInternal[index]; if(find_if(newInternal.begin(), newInternal.end(), PlaylistItemCompare(item)) == newInternal.end()) { // need to delete it vector<PlaylistItem*>::iterator position; if((position = find_if(newExternal.begin(), newExternal.end(), PlaylistItemCompare(item))) != newExternal.end()) { // need to download it to temp file first // and then upload it to other card // in the next stage... string itemPath = item->URL(); string downloadPath = tempPath; downloadPath += DIR_MARKER_STR; downloadPath.insert(downloadPath.size(), itemPath, itemPath.rfind('/') + 1, itemPath.size()); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioInternal.RxFile(downloadPath.c_str(), rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioInternal.GetErrorID(); event.eventString = "Download failed, "; event.eventString += rioInternal.GetErrorStr(); function(&event, cookie); } if(rioInternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } length = _MAX_PATH; FilePathToURL(downloadPath.c_str(), path, &length); (*position)->SetURL(path); } string::size_type pos = item->URL().rfind("/") + 1; const char* cp = item->URL().c_str(); if(!rioInternal.RemoveFile(cp + pos)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioInternal.GetErrorID(); event.eventString = "Delete failed, "; event.eventString += rioInternal.GetErrorStr(); function(&event, cookie); } result = kError_UnknownErr; break; } delete item; origInternal[index] = NULL; } } if(IsntError(result)) { count = origExternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origExternal[index]; if(find_if(newExternal.begin(), newExternal.end(), PlaylistItemCompare(item)) == newExternal.end()) { // need to delete it vector<PlaylistItem*>::iterator position; if((position = find_if(newInternal.begin(), newInternal.end(), PlaylistItemCompare(item))) != newInternal.end()) { // need to download it to temp file first // and then upload it to other card // in the next stage... string itemPath = item->URL(); string downloadPath = tempPath; downloadPath += DIR_MARKER_STR; downloadPath.insert(downloadPath.size(), itemPath, itemPath.rfind('/') + 1, itemPath.size()); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioExternal.RxFile(downloadPath.c_str(), rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioExternal.GetErrorID(); event.eventString = "Download failed, "; event.eventString += rioExternal.GetErrorStr(); function(&event, cookie); } if(rioInternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } length = _MAX_PATH; FilePathToURL(downloadPath.c_str(), path, &length); (*position)->SetURL(path); } string::size_type pos = item->URL().rfind("/") + 1; const char* cp = item->URL().c_str(); if(!rioExternal.RemoveFile(cp + pos)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioExternal.GetErrorID(); event.eventString = "Delete failed, "; event.eventString += rioExternal.GetErrorStr(); function(&event, cookie); } result = kError_UnknownErr; break; } delete item; origExternal[index] = NULL; } } } } // if all is well we add new files // to each card if(IsntError(result)) { // remove NULLs caused by deletes origInternal.erase( remove(origInternal.begin(), origInternal.end(), (PlaylistItem*)NULL), origInternal.end()); origExternal.erase( remove(origExternal.begin(), origExternal.end(), (PlaylistItem*)NULL), origExternal.end()); // sync deletes back to the cards rioInternal.TxDirectory(); rioExternal.TxDirectory(); if(function) { PLMEvent event; event.type = kPLMEvent_Status; event.eventString = "Uploading new files..."; function(&event, cookie); } count = newInternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = newInternal[index]; if(item->URL().find("file://") != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioInternal.TxFile(path, rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioInternal.GetErrorID(); event.eventString = "Upload failed, "; event.eventString += rioInternal.GetErrorStr(); function(&event, cookie); } if(rioInternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } origInternal.push_back(new PlaylistItem(*item)); } } if(IsntError(result)) { count = newExternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = newExternal[index]; if(item->URL().find("file://") != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); RioProgressStruct ps; memset(&ps, 0x00, sizeof(ps)); ps.function = function; ps.cookie = cookie; ps.item = item; if(!rioExternal.TxFile(path, rioProgress, &ps)) { if(function) { PLMEvent event; event.type = kPLMEvent_Error; event.data.errorData.errorCode = rioExternal.GetErrorID(); event.eventString = "Upload failed, "; event.eventString += rioExternal.GetErrorStr(); function(&event, cookie); } if(rioExternal.GetErrorID() == CRIO_ERROR_INTERRUPTED) result = kError_UserCancel; else result = kError_UnknownErr; break; } origExternal.push_back(new PlaylistItem(*item)); } } } } // finally put it all in the correct order // and we should be done! if(IsntError(result)) { uint32 entryOrder[ CRIO_MAX_DIRENTRY ]; count = newInternal.size(); if(count) { for(index = 0; index < count; index++) { vector<PlaylistItem*>::iterator position; PlaylistItem* item = newInternal[index]; if((position = find_if(origInternal.begin(), origInternal.end(), PlaylistItemCompare(item))) != origInternal.end()) { //#ifdef WIN32 // distance(origInternal.begin(), position /*, entryOrder[index] */ ); //#else entryOrder[index] = distance(origInternal.begin(), position /*, entryOrder[index] */ ); //#endif } } rioInternal.SetFileOrder(entryOrder, count); } count = newExternal.size(); if(count) { for(index = 0; index < count; index++) { vector<PlaylistItem*>::iterator position; PlaylistItem* item = newExternal[index]; if((position = find_if(origExternal.begin(), origExternal.end(), PlaylistItemCompare(item))) != origExternal.end()) { //#ifdef WIN32 // distance(origExternal.begin(), position /*, entryOrder[index] */ ); //#else entryOrder[index] = distance(origExternal.begin(), position /*, entryOrder[index] */ ); //#endif } } rioExternal.SetFileOrder(entryOrder, count); } // sync uploads back to the cards rioInternal.TxDirectory(); rioExternal.TxDirectory(); } if(function) { PLMEvent event; event.type = kPLMEvent_Done; function(&event, cookie); } // clean up length = _MAX_PATH; FilePathToURL(tempPath, path, &length); strcpy(tempPath, path); count = origInternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origInternal[index]; if(item->URL().find(tempPath) != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); remove(path); } delete item; } count = origExternal.size(); for(index = 0; index < count; index++) { PlaylistItem* item = origExternal[index]; if(item->URL().find(tempPath) != string::npos) { length = _MAX_PATH; URLToFilePath(item->URL().c_str(), path, &length); remove(path); } delete item; } URLToFilePath(tempPath, path, &length); rmdir(path); delete [] tempPath; delete [] path; } } } return result; }
// ValidateItemLayout void SlideShowPlaylist::ValidateItemLayout() { int64 duration = Value(PROPERTY_DURATION, (int64)0); if (duration == 0) return; int64 transitionDuration = Value(PROPERTY_TRANSITION_DURATION, (int64)0); // TODO: transition mode... int32 count = CountItems(); BList managedItems; int64 minDuration = 0; int64 minItemDuration = transitionDuration * 3; int64 fixedItemsDuration = 0; int64 maxDuration = 0; int32 variableItemCount = 0; for (int32 i = 0; i < count; i++) { PlaylistItem* item = ItemAtFast(i); if (item->Track() > 1) // not a "managed" item continue; managedItems.AddItem(item); if (item->HasMaxDuration()) { int64 maxItemDuration = item->MaxDuration(); minDuration += maxItemDuration; fixedItemsDuration += maxItemDuration; if (minItemDuration > maxItemDuration) minItemDuration = maxItemDuration; } else { minDuration += 3 * transitionDuration; variableItemCount++; } maxDuration += item->MaxDuration(); } count = managedItems.CountItems(); if (count == 0) return; if (duration < minDuration) duration = minDuration; if (duration > maxDuration) duration = maxDuration; // limit transition duration to 1/3 of the minimum item duration int64 maxTransitionDuration = minItemDuration / 3; if (transitionDuration > maxTransitionDuration) transitionDuration = maxTransitionDuration; int64 variableItemsDuration = duration - fixedItemsDuration + transitionDuration * (count - variableItemCount); int64 startFrame = 0; int64 lastVariableStartFrame = 0; int32 variableItemIndex = 0; for (int32 i = 0; i < count; i++) { PlaylistItem* item = (PlaylistItem*)managedItems.ItemAtFast(i); // overlapping items item->SetClipOffset(0); item->SetTrack(i & 1); int64 nextStartFrame; if (item->HasMaxDuration()) { nextStartFrame = startFrame + item->MaxDuration() - transitionDuration; } else { variableItemIndex++; int64 nextVariableStartFrame = (variableItemsDuration - transitionDuration) * variableItemIndex / variableItemCount; nextStartFrame = startFrame + nextVariableStartFrame - lastVariableStartFrame; lastVariableStartFrame = nextVariableStartFrame; } item->SetStartFrame(startFrame); item->SetDuration(nextStartFrame - startFrame + transitionDuration); startFrame = nextStartFrame; // transition PropertyAnimator* animator = item->AlphaAnimator(); if (!animator) continue; AutoNotificationSuspender _(animator); // remove all keyframes to get a clean start animator->MakeEmpty(); KeyFrame* first = animator->InsertKeyFrameAt(0LL); KeyFrame* last = animator->InsertKeyFrameAt(item->Duration() - 1); if (!first || !last) continue; first->SetScale(1.0); last->SetScale(1.0); // transition in top items if (transitionDuration > 0 && !(i & 1)) { // item on first track, animated opacity property if (i > 0) { // fade in KeyFrame* key = animator->InsertKeyFrameAt(transitionDuration); key->SetScale(1.0); first->SetScale(0.0); } if (i < count - 1) { // fade out KeyFrame* key = animator->InsertKeyFrameAt( item->Duration() - 1 - transitionDuration); key->SetScale(1.0); last->SetScale(0.0); } } } }