* PlaylistFileReader.cpp - Media Player for the Haiku Operating System
*
* Copyright (C) 2006 Marcus Overhagen <marcus@overhagen.de>
* Copyright (C) 2007-2009 Stephan AΓmus <superstippi@gmx.de> (MIT ok)
* Copyright (C) 2008-2009 Fredrik ModΓ©en <[FirstName]@[LastName].se> (MIT ok)
*
* Released under the terms of the MIT license.
*/
#include "PlaylistFileReader.h"
#include <cctype>
#include <new>
#include <stdio.h>
#include <strings.h>
#include <Path.h>
#include <Url.h>
#include "FileReadWrite.h"
#include "Playlist.h"
using std::isdigit;
using std::nothrow;
PlaylistFileReader*
PlaylistFileReader::GenerateReader(const entry_ref& ref)
{
PlaylistFileType type = _IdentifyType(ref);
PlaylistFileReader* reader = NULL;
if (type == m3u)
reader = new (nothrow) M3uReader;
else if (type == pls)
reader = new (nothrow) PlsReader;
return reader;
}
int32
PlaylistFileReader::_AppendItemToPlaylist(const BString& entry, Playlist* playlist)
{
bool validItem = true;
int32 assignedIndex = -1;
BPath path(entry.String());
entry_ref refPath;
status_t err = get_ref_for_path(path.Path(), &refPath);
PlaylistItem* item = NULL;
if (err == B_OK)
item = new (nothrow) FilePlaylistItem(refPath);
else {
BUrl url(entry, true);
if (url.IsValid())
item = new (nothrow) UrlPlaylistItem(url);
else {
printf("Error - %s: [%" B_PRIx32 "]\n", strerror(err), err);
validItem = false;
}
}
if (validItem) {
if (item == NULL)
delete item;
else {
bool itemAdded = playlist->AddItem(item);
if (!itemAdded)
delete item;
else
assignedIndex = playlist->IndexOf(item);
}
}
return assignedIndex;
}
PlaylistFileType
PlaylistFileReader::_IdentifyType(const entry_ref& ref)
{
BString path(BPath(&ref).Path());
PlaylistFileType type = unknown;
if (path.FindLast(".m3u") == path.CountChars() - 4
|| path.FindLast(".m3u8") == path.CountChars() - 5)
type = m3u;
else if (path.FindLast(".pls") == path.CountChars() - 4)
type = pls;
return type;
}
void
M3uReader::AppendToPlaylist(const entry_ref& ref, Playlist* playlist)
{
BFile file(&ref, B_READ_ONLY);
FileReadWrite lineReader(&file);
BString line;
while (lineReader.Next(line)) {
if (line.FindFirst("#") != 0)
_AppendItemToPlaylist(line, playlist);
line.Truncate(0);
}
}
void
PlsReader::AppendToPlaylist(const entry_ref& ref, Playlist* playlist)
{
BString plsEntries;
BString plsVersion;
int32 lastAssignedIndex = -1;
BFile file(&ref, B_READ_ONLY);
FileReadWrite lineReader(&file);
BString line;
lineReader.Next(line);
if (line != "[playlist]") {
printf("Error - Invalid .pls file\n");
return;
}
line.Truncate(0);
while (true) {
bool lineRead = lineReader.Next(line);
if (lineRead == false)
break;
int32 equalIndex = line.FindFirst("=");
if (equalIndex == B_ERROR) {
line.Truncate(0);
continue;
}
BString lineType;
BString trackNumber;
if (isdigit(line[equalIndex - 1])) {
int32 trackIndex = equalIndex - 1;
while (isdigit(line[trackIndex - 1]))
trackIndex--;
line.CopyInto(lineType, 0, trackIndex);
line.CopyInto(trackNumber, trackIndex, equalIndex - trackIndex);
} else {
line.CopyInto(lineType, 0, equalIndex);
}
BString lineContent;
line.CopyInto(lineContent, equalIndex + 1, line.Length() - (equalIndex + 1));
if (lineType == "File") {
lastAssignedIndex = _AppendItemToPlaylist(lineContent, playlist);
} else if (lineType == "Title") {
_ParseTitleLine(lineContent, playlist, lastAssignedIndex);
} else if (lineType == "Length") {
_ParseLengthLine(lineContent, playlist, lastAssignedIndex);
} else if (lineType == "NumberOfEntries") {
plsEntries = lineContent;
} else if (lineType == "Version") {
plsVersion = lineContent;
} else {
}
line.Truncate(0);
}
}
status_t
PlsReader::_ParseTitleLine(const BString& title, Playlist* playlist,
const int32 lastAssignedIndex)
{
status_t err;
if (lastAssignedIndex != -1) {
err = playlist->ItemAt(lastAssignedIndex)->SetAttribute(
PlaylistItem::ATTR_STRING_TITLE, title);
} else
err = B_CANCELED;
if (err != B_OK)
printf("Error - %s: [%" B_PRIx32 "]\n", strerror(err), err);
return err;
}
status_t
PlsReader::_ParseLengthLine(const BString& length, Playlist* playlist,
const int32 lastAssignedIndex)
{
status_t err;
if (lastAssignedIndex != -1)
{
int64 lengthInt = strtoll(length.String(), NULL, 10);
err = playlist->ItemAt(lastAssignedIndex)->SetAttribute(
PlaylistItem::ATTR_INT64_DURATION, lengthInt);
} else
err = B_CANCELED;
if (err != B_OK)
printf("Error - %s: [%" B_PRIx32 "]\n", strerror(err), err);
return err;
}