You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/juk/cache.cpp

324 lines
8.3 KiB

/***************************************************************************
begin : Sat Sep 7 2002
copyright : (C) 2002 - 2004 by Scott Wheeler
email : wheeler@kde.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <kstandarddirs.h>
#include <kmessagebox.h>
#include <tdeconfig.h>
#include <klocale.h>
#include <tdeactionclasses.h>
#include <kdebug.h>
#include <tqdir.h>
#include <tqbuffer.h>
#include "cache.h"
#include "tag.h"
#include "searchplaylist.h"
#include "historyplaylist.h"
#include "upcomingplaylist.h"
#include "folderplaylist.h"
#include "playlistcollection.h"
#include "actioncollection.h"
using namespace ActionCollection;
static const int playlistCacheVersion = 2;
enum PlaylistType
{
Normal = 0,
Search = 1,
History = 2,
Upcoming = 3,
Folder = 4
};
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
Cache *Cache::instance()
{
static Cache cache;
// load() indirectly calls instance() so we have to protect against recursion.
static bool loaded = false;
if(!loaded) {
loaded = true;
cache.load();
}
return &cache;
}
void Cache::save()
{
TQString dirName = TDEGlobal::dirs()->saveLocation("appdata");
TQString cacheFileName = dirName + "cache.new";
TQFile f(cacheFileName);
if(!f.open(IO_WriteOnly))
return;
TQByteArray data;
TQDataStream s(data, IO_WriteOnly);
for(Iterator it = begin(); it != end(); ++it) {
s << (*it).absFilePath();
s << *it;
}
TQDataStream fs(&f);
TQ_INT32 checksum = tqChecksum(data.data(), data.size());
fs << TQ_INT32(m_currentVersion)
<< checksum
<< data;
f.close();
TQDir(dirName).rename("cache.new", "cache");
}
void Cache::loadPlaylists(PlaylistCollection *collection) // static
{
TQString playlistsFile = TDEGlobal::dirs()->saveLocation("appdata") + "playlists";
TQFile f(playlistsFile);
if(!f.open(IO_ReadOnly))
return;
TQDataStream fs(&f);
TQ_INT32 version;
fs >> version;
switch(version) {
case 1:
case 2:
{
// Our checksum is only for the values after the version and checksum so
// we want to get a byte array with just the checksummed data.
TQByteArray data;
TQ_UINT16 checksum;
fs >> checksum >> data;
if(checksum != tqChecksum(data.data(), data.size()))
return;
// Create a new stream just based on the data.
TQDataStream s(data, IO_ReadOnly);
while(!s.atEnd()) {
TQ_INT32 playlistType;
s >> playlistType;
Playlist *playlist = 0;
switch(playlistType) {
case Search:
{
SearchPlaylist *p = new SearchPlaylist(collection);
s >> *p;
playlist = p;
break;
}
case History:
{
action<TDEToggleAction>("showHistory")->setChecked(true);
collection->setHistoryPlaylistEnabled(true);
s >> *collection->historyPlaylist();
playlist = collection->historyPlaylist();
break;
}
case Upcoming:
{
/*
collection->setUpcomingPlaylistEnabled(true);
Playlist *p = collection->upcomingPlaylist();
action<TDEToggleAction>("saveUpcomingTracks")->setChecked(true);
s >> *p;
playlist = p;
*/
break;
}
case Folder:
{
FolderPlaylist *p = new FolderPlaylist(collection);
s >> *p;
playlist = p;
break;
}
default:
Playlist *p = new Playlist(collection, true);
s >> *p;
playlist = p;
break;
}
if(version == 2) {
TQ_INT32 sortColumn;
s >> sortColumn;
if(playlist)
playlist->setSorting(sortColumn);
}
}
break;
}
default:
{
// Because the original version of the playlist cache did not contain a
// version number, we want to revert to the beginning of the file before
// reading the data.
f.reset();
while(!fs.atEnd()) {
Playlist *p = new Playlist(collection);
fs >> *p;
}
break;
}
}
f.close();
}
void Cache::savePlaylists(const PlaylistList &playlists)
{
TQString dirName = TDEGlobal::dirs()->saveLocation("appdata");
TQString playlistsFile = dirName + "playlists.new";
TQFile f(playlistsFile);
if(!f.open(IO_WriteOnly))
return;
TQByteArray data;
TQDataStream s(data, IO_WriteOnly);
for(PlaylistList::ConstIterator it = playlists.begin(); it != playlists.end(); ++it) {
if(*it) {
if(dynamic_cast<HistoryPlaylist *>(*it)) {
s << TQ_INT32(History)
<< *static_cast<HistoryPlaylist *>(*it);
}
else if(dynamic_cast<SearchPlaylist *>(*it)) {
s << TQ_INT32(Search)
<< *static_cast<SearchPlaylist *>(*it);
}
else if(dynamic_cast<UpcomingPlaylist *>(*it)) {
if(!action<TDEToggleAction>("saveUpcomingTracks")->isChecked())
continue;
s << TQ_INT32(Upcoming)
<< *static_cast<UpcomingPlaylist *>(*it);
}
else if(dynamic_cast<FolderPlaylist *>(*it)) {
s << TQ_INT32(Folder)
<< *static_cast<FolderPlaylist *>(*it);
}
else {
s << TQ_INT32(Normal)
<< *(*it);
}
s << TQ_INT32((*it)->sortColumn());
}
}
TQDataStream fs(&f);
fs << TQ_INT32(playlistCacheVersion);
fs << tqChecksum(data.data(), data.size());
fs << data;
f.close();
TQDir(dirName).rename("playlists.new", "playlists");
}
bool Cache::cacheFileExists() // static
{
return TQFile::exists(TDEGlobal::dirs()->saveLocation("appdata") + "cache");
}
////////////////////////////////////////////////////////////////////////////////
// protected methods
////////////////////////////////////////////////////////////////////////////////
Cache::Cache() : FileHandleHash()
{
}
void Cache::load()
{
TQString cacheFileName = TDEGlobal::dirs()->saveLocation("appdata") + "cache";
TQFile f(cacheFileName);
if(!f.open(IO_ReadOnly))
return;
CacheDataStream s(TQT_TQIODEVICE(&f));
TQ_INT32 version;
s >> version;
TQBuffer buffer;
// Do the version specific stuff.
switch(version) {
case 1: {
s.setCacheVersion(1);
TQ_INT32 checksum;
TQByteArray data;
s >> checksum
>> data;
buffer.setBuffer(data);
buffer.open(IO_ReadOnly);
s.setDevice(&buffer);
if(checksum != tqChecksum(data.data(), data.size())) {
KMessageBox::sorry(0, i18n("The music data cache has been corrupted. JuK "
"needs to rescan it now. This may take some time."));
return;
}
break;
}
default: {
s.device()->reset();
s.setCacheVersion(0);
break;
}
}
// Read the cached tags.
while(!s.atEnd()) {
TQString fileName;
s >> fileName;
fileName.squeeze();
FileHandle f(fileName, s);
}
}