* Cleanup with regards to file panel usage. There are two global file panels

now maintained by the application. (So that the last used folder is more
  consistently remembered.)
* Added a message protocol for using the file panels from other loopers.
* Implemented playlist saving and loading for the binary (BMessage-based)
  format. There were some beginnings for supporting a m3u-like text-based format
  as well.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27955 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2008-10-10 18:55:06 +00:00
parent fe93c7b3ea
commit 126ce07138
10 changed files with 458 additions and 101 deletions
+183 -26
View File
@@ -2,7 +2,7 @@
* MainApp.cpp - Media Player for the Haiku Operating System
*
* Copyright (C) 2006 Marcus Overhagen <[email protected]>
* Copyright (C) 2008 Stephan Aßmus <[email protected]>
* Copyright (C) 2008 Stephan Aßmus <[email protected]> (MIT Ok)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -23,6 +23,7 @@
#include <Alert.h>
#include <Autolock.h>
#include <Entry.h>
#include <FilePanel.h>
#include <MediaRoster.h>
#include <Path.h>
#include <Roster.h>
@@ -35,7 +36,7 @@
#include "SettingsWindow.h"
MainApp *gMainApp;
MainApp* gMainApp;
const char* kAppSig = "application/x-vnd.Haiku-MediaPlayer";
static const char* kMediaServerSig = "application/x-vnd.Be.media-server";
@@ -45,9 +46,13 @@ static const char* kMediaServerAddOnSig = "application/x-vnd.Be.addon-host";
MainApp::MainApp()
: BApplication(kAppSig),
fPlayerCount(0),
//fFirstWindow(NewWindow()),
fFirstWindow(NULL),
fSettingsWindow(NULL),
fOpenFilePanel(NULL),
fSaveFilePanel(NULL),
fLastFilePanelFolder(),
fMediaServerRunning(false),
fMediaAddOnServerRunning(false)
{
@@ -56,6 +61,8 @@ MainApp::MainApp()
MainApp::~MainApp()
{
delete fOpenFilePanel;
delete fSaveFilePanel;
}
@@ -63,7 +70,8 @@ bool
MainApp::QuitRequested()
{
// Note: This needs to be done here, SettingsWindow::QuitRequested()
// returns "false" always.
// returns "false" always. (Standard BApplication quit procedure will
// hang otherwise.)
if (fSettingsWindow && fSettingsWindow->Lock())
fSettingsWindow->Quit();
fSettingsWindow = NULL;
@@ -76,7 +84,7 @@ BWindow*
MainApp::FirstWindow()
{
BAutolock _(this);
if (fFirstWindow)
if (fFirstWindow != NULL)
return fFirstWindow;
return NewWindow();
}
@@ -85,13 +93,12 @@ MainApp::FirstWindow()
BWindow*
MainApp::NewWindow()
{
BWindow* win;
BAutolock _(this);
fPlayerCount++;
win = new MainWin();
if (!fFirstWindow)
fFirstWindow = win;
return win;
BWindow* window = new MainWin();
if (fFirstWindow == NULL)
fFirstWindow = window;
return window;
}
@@ -130,7 +137,7 @@ MainApp::ReadyToRun()
void
MainApp::RefsReceived(BMessage *msg)
MainApp::RefsReceived(BMessage* message)
{
// The user dropped a file (or files) on this app's icon,
// or double clicked a file that's handled by this app.
@@ -142,14 +149,9 @@ MainApp::RefsReceived(BMessage *msg)
// window.
printf("MainApp::RefsReceived\n");
entry_ref ref;
for (int i = 0; B_OK == msg->FindRef("refs", i, &ref); i++) {
BWindow *win;
win = NewWindow();
BMessage m(B_REFS_RECEIVED);
m.AddRef("refs", &ref);
win->PostMessage(&m);
}
BWindow* window = NewWindow();
if (window)
window->PostMessage(message);
}
@@ -245,6 +247,20 @@ MainApp::MessageReceived(BMessage* message)
_ShowSettingsWindow();
break;
case M_SHOW_OPEN_PANEL:
_ShowOpenFilePanel(message);
break;
case M_SHOW_SAVE_PANEL:
_ShowSaveFilePanel(message);
break;
case M_OPEN_PANEL_RESULT:
_HandleOpenPanelResult(message);
break;
case M_SAVE_PANEL_RESULT:
_HandleSavePanelResult(message);
break;
default:
BApplication::MessageReceived(message);
break;
@@ -259,6 +275,9 @@ MainApp::AboutRequested()
}
// #pragma mark -
void
MainApp::_BroadcastMessage(const BMessage& _message)
{
@@ -272,17 +291,155 @@ MainApp::_BroadcastMessage(const BMessage& _message)
void
MainApp::_ShowSettingsWindow()
{
if (fSettingsWindow->Lock()) {
if (fSettingsWindow->IsHidden())
fSettingsWindow->Show();
else
fSettingsWindow->Activate();
fSettingsWindow->Unlock();
BAutolock lock(fSettingsWindow);
if (!lock.IsLocked())
return;
// If the window is already showing, don't jerk the workspaces around,
// just pull it to the current one.
uint32 workspace = 1UL << (uint32)current_workspace();
uint32 windowWorkspaces = fSettingsWindow->Workspaces();
if ((windowWorkspaces & workspace) == 0) {
// window in a different workspace, reopen in current
fSettingsWindow->SetWorkspaces(workspace);
}
if (fSettingsWindow->IsHidden())
fSettingsWindow->Show();
else
fSettingsWindow->Activate();
}
// #pragma mark -
// #pragma mark - file panels
void
MainApp::_ShowOpenFilePanel(const BMessage* message)
{
if (fOpenFilePanel == NULL) {
BMessenger target(this);
fOpenFilePanel = new BFilePanel(B_OPEN_PANEL, &target);
}
_ShowFilePanel(fOpenFilePanel, M_OPEN_PANEL_RESULT, message,
"Open", "Open");
}
void
MainApp::_ShowSaveFilePanel(const BMessage* message)
{
if (fSaveFilePanel == NULL) {
BMessenger target(this);
fSaveFilePanel = new BFilePanel(B_SAVE_PANEL, &target);
}
_ShowFilePanel(fSaveFilePanel, M_SAVE_PANEL_RESULT, message,
"Save", "Save");
}
void
MainApp::_ShowFilePanel(BFilePanel* panel, uint32 command,
const BMessage* message, const char* defaultTitle,
const char* defaultLabel)
{
// printf("_ShowFilePanel()\n");
// message->PrintToStream();
BMessage panelMessage(command);
if (message != NULL) {
BMessage targetMessage;
if (message->FindMessage("message", &targetMessage) == B_OK)
panelMessage.AddMessage("message", &targetMessage);
BMessenger target;
if (message->FindMessenger("target", &target) == B_OK)
panelMessage.AddMessenger("target", target);
const char* panelTitle;
if (message->FindString("title", &panelTitle) != B_OK)
panelTitle = defaultTitle;
{
BString finalPanelTitle = "MediaPlayer: ";
finalPanelTitle << panelTitle;
BAutolock lock(panel->Window());
panel->Window()->SetTitle(finalPanelTitle.String());
}
const char* buttonLabel;
if (message->FindString("label", &buttonLabel) != B_OK)
buttonLabel = defaultLabel;
panel->SetButtonLabel(B_DEFAULT_BUTTON, buttonLabel);
}
// panelMessage.PrintToStream();
panel->SetMessage(&panelMessage);
if (fLastFilePanelFolder != entry_ref()) {
panel->SetPanelDirectory(&fLastFilePanelFolder);
}
panel->Show();
}
void
MainApp::_HandleOpenPanelResult(const BMessage* message)
{
_HandleFilePanelResult(fOpenFilePanel, message);
}
void
MainApp::_HandleSavePanelResult(const BMessage* message)
{
_HandleFilePanelResult(fSaveFilePanel, message);
}
void
MainApp::_HandleFilePanelResult(BFilePanel* panel, const BMessage* message)
{
// printf("_HandleFilePanelResult()\n");
// message->PrintToStream();
panel->GetPanelDirectory(&fLastFilePanelFolder);
BMessage targetMessage;
if (message->FindMessage("message", &targetMessage) != B_OK)
targetMessage.what = message->what;
BMessenger target;
if (message->FindMessenger("target", &target) != B_OK) {
if (targetMessage.what == M_OPEN_PANEL_RESULT
|| targetMessage.what == M_SAVE_PANEL_RESULT) {
// prevent endless message cycle
return;
}
// send result message to ourselves
target = BMessenger(this);
}
// copy the important contents of the message
// save panel
entry_ref directory;
if (message->FindRef("directory", &directory) == B_OK)
targetMessage.AddRef("directory", &directory);
const char* name;
if (message->FindString("name", &name) == B_OK)
targetMessage.AddString("name", name);
// open panel
entry_ref ref;
for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++)
targetMessage.AddRef("refs", &ref);
target.SendMessage(&targetMessage);
}
// #pragma mark - main
int
+34
View File
@@ -22,18 +22,36 @@
#define __MAIN_APP_H
#include <Application.h>
#include <Entry.h>
#include "MainWin.h"
enum {
M_PLAYER_QUIT = 'plqt',
M_SETTINGS = 'stng',
M_SHOW_OPEN_PANEL = 'swop',
M_SHOW_SAVE_PANEL = 'swsp',
// "target" - This BMessenger will be sent the result message.
// "message" - This message will be sent back to the target, with
// the additional fields that a BFilePanel provides.
// If no result message is specified, the constants below
// will be used.
// "title" - String that will be used to name the panel window.
// "label" - String that will be used to name the Default button.
M_OPEN_PANEL_RESULT = 'oprs',
M_SAVE_PANEL_RESULT = 'sprs',
M_MEDIA_SERVER_STARTED = 'msst',
M_MEDIA_SERVER_QUIT = 'msqt'
};
class BFilePanel;
class SettingsWindow;
class MainApp : public BApplication {
public:
MainApp();
@@ -55,10 +73,26 @@ private:
void _ShowSettingsWindow();
void _BroadcastMessage(const BMessage& message);
void _ShowOpenFilePanel(const BMessage* message);
void _ShowSaveFilePanel(const BMessage* message);
void _ShowFilePanel(BFilePanel* panel,
uint32 command, const BMessage* message,
const char* defaultTitle,
const char* defaultLabel);
void _HandleOpenPanelResult(const BMessage* message);
void _HandleSavePanelResult(const BMessage* message);
void _HandleFilePanelResult(BFilePanel* panel,
const BMessage* message);
int32 fPlayerCount;
BWindow* fFirstWindow;
SettingsWindow* fSettingsWindow;
BFilePanel* fOpenFilePanel;
BFilePanel* fSaveFilePanel;
entry_ref fLastFilePanelFolder;
bool fMediaServerRunning;
bool fMediaAddOnServerRunning;
};
+10 -9
View File
@@ -101,7 +101,6 @@ enum {
MainWin::MainWin()
: BWindow(BRect(100,100,400,300), NAME, B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS /* | B_WILL_ACCEPT_FIRST_CLICK */),
fFilePanel(NULL),
fInfoWin(NULL),
fPlaylistWindow(NULL),
fHasFile(false),
@@ -218,7 +217,6 @@ MainWin::~MainWin()
fPlaylistWindow->Quit();
delete fPlaylist;
delete fFilePanel;
// quit the Controller looper thread
thread_id controllerThread = fController->Thread();
@@ -469,14 +467,17 @@ MainWin::MessageReceived(BMessage *msg)
case M_FILE_NEWPLAYER:
gMainApp->NewWindow();
break;
case M_FILE_OPEN:
if (!fFilePanel) {
fFilePanel = new BFilePanel();
fFilePanel->SetTarget(BMessenger(0, this));
fFilePanel->SetPanelDirectory("/boot/home/");
}
fFilePanel->Show();
case M_FILE_OPEN: {
BMessenger target(this);
BMessage result(B_REFS_RECEIVED);
BMessage appMessage(M_SHOW_OPEN_PANEL);
appMessage.AddMessenger("target", target);
appMessage.AddMessage("message", &result);
appMessage.AddString("title", "Open Clips");
appMessage.AddString("label", "Open");
be_app->PostMessage(&appMessage);
break;
}
case M_FILE_INFO:
ShowFileInfo();
break;
-2
View File
@@ -25,7 +25,6 @@
#include <Menu.h>
#include <Button.h>
#include <Slider.h>
#include <FilePanel.h>
#include "Controller.h"
#include "ControllerView.h"
@@ -101,7 +100,6 @@ private:
BMenuBar* fMenuBar;
BView* fBackground;
VideoView* fVideoView;
BFilePanel* fFilePanel;
ControllerView* fControls;
InfoWin* fInfoWin;
PlaylistWindow* fPlaylistWindow;
@@ -11,6 +11,7 @@
#include <new>
#include <stdio.h>
#include <Alert.h>
#include <Autolock.h>
#include "Playlist.h"
@@ -39,8 +40,12 @@ ImportPLItemsCommand::ImportPLItemsCommand(Playlist* playlist,
temp.AppendRefs(refsMessage);
fNewCount = temp.CountItems();
if (fNewCount <= 0)
if (fNewCount <= 0) {
BAlert* alert = new BAlert("Nothing to Play", "None of the files "
"you wanted to play appear to be media files.", "Ok");
alert->Go(NULL);
return;
}
fNewRefs = new (nothrow) entry_ref[fNewCount];
if (!fNewRefs)
+71 -28
View File
@@ -75,7 +75,7 @@ static const char* kPathKey = "path";
status_t
Playlist::UnArchive(const BMessage* archive)
Playlist::Unarchive(const BMessage* archive)
{
if (archive == NULL)
return B_BAD_VALUE;
@@ -118,6 +118,61 @@ Playlist::Archive(BMessage* into) const
}
static const uint32 kPlaylistMagicBytes = 'MPPL';
static const char* kTextPlaylistMimeString = "text/x-playlist";
static const char* kBinaryPlaylistMimeString
= "application/x-vnd.haiku-playlist";
status_t
Playlist::Unflatten(BDataIO* stream)
{
if (stream == NULL)
return B_BAD_VALUE;
uint32 magicBytes;
ssize_t read = stream->Read(&magicBytes, 4);
if (read != 4) {
if (read < 0)
return (status_t)read;
return B_IO_ERROR;
}
if (B_LENDIAN_TO_HOST_INT32(magicBytes) != kPlaylistMagicBytes)
return B_BAD_VALUE;
BMessage archive;
status_t ret = archive.Unflatten(stream);
if (ret != B_OK)
return ret;
return Unarchive(&archive);
}
status_t
Playlist::Flatten(BDataIO* stream) const
{
if (stream == NULL)
return B_BAD_VALUE;
BMessage archive;
status_t ret = Archive(&archive);
if (ret != B_OK)
return ret;
uint32 magicBytes = B_HOST_TO_LENDIAN_INT32(kPlaylistMagicBytes);
ssize_t written = stream->Write(&magicBytes, 4);
if (written != 4) {
if (written < 0)
return (status_t)written;
return B_IO_ERROR;
}
return archive.Flatten(stream);
}
// #pragma mark - list access
@@ -386,7 +441,7 @@ Playlist::AppendToPlaylistRecursive(const entry_ref& ref, Playlist* playlist)
if (_IsMediaFile(mimeString)) {
//printf("Adding\n");
playlist->AddRef(ref);
} else if (_IsPlaylist(mimeString)) {
} else if (_IsTextPlaylist(mimeString)) {
//printf("RunPlaylist thing\n");
BFile file(&ref, B_READ_ONLY);
FileReadWrite lineReader(&file);
@@ -408,6 +463,11 @@ Playlist::AppendToPlaylistRecursive(const entry_ref& ref, Playlist* playlist)
} else
printf("Error - No File Found in playlist\n");
}
} else if (_IsBinaryPlaylist(mimeString)) {
BFile file(&ref, B_READ_ONLY);
Playlist temp;
if (temp.Unflatten(&file) == B_OK)
playlist->AdoptPlaylist(temp, playlist->CountItems());
} else
printf("MIME Type = %s\n", mimeString.String());
}
@@ -431,30 +491,6 @@ Playlist::playlist_cmp(const void *p1, const void *p2)
}
/*static*/ void
Playlist::_AddPlayListFileToPlayList(const entry_ref& ref, Playlist* playlist)
{
BFile file(&ref, B_READ_ONLY);
FileReadWrite lineReader(&file);
BString str;
while (lineReader.Next(str)) {
BPath path = BPath(str.String());
entry_ref refPath;
status_t err;
if ((err = get_ref_for_path(path.Path(), &refPath)) == B_OK) {
AppendToPlaylistRecursive(refPath, playlist);
} else
printf("Error - %s: [%lx]\n", strerror(err), (int32) err);
}
/*
Read line for x to the end of file (while?)
make a enty_ref and call AppendToPlaylistRecursive(with new entry, playlist)
*/
}
/*static*/ bool
Playlist::_IsMediaFile(const BString& mimeString)
{
@@ -472,9 +508,16 @@ Playlist::_IsMediaFile(const BString& mimeString)
/*static*/ bool
Playlist::_IsPlaylist(const BString& mimeString)
Playlist::_IsTextPlaylist(const BString& mimeString)
{
return mimeString.Compare("text/x-playlist") == 0;
return mimeString.Compare(kTextPlaylistMimeString) == 0;
}
/*static*/ bool
Playlist::_IsBinaryPlaylist(const BString& mimeString)
{
return mimeString.Compare(kBinaryPlaylistMimeString) == 0;
}
+7 -4
View File
@@ -26,6 +26,7 @@
#include <List.h>
#include <Locker.h>
class BDataIO;
class BMessage;
class BString;
@@ -49,9 +50,12 @@ public:
Playlist();
~Playlist();
// archiving
status_t UnArchive(const BMessage* archive);
status_t Unarchive(const BMessage* archive);
status_t Archive(BMessage* into) const;
status_t Unflatten(BDataIO* stream);
status_t Flatten(BDataIO* stream) const;
// list functionality
void MakeEmpty();
@@ -91,10 +95,9 @@ public:
private:
static int playlist_cmp(const void* p1, const void* p2);
static bool _IsMediaFile(const BString& mimeString);
static bool _IsPlaylist(const BString& mimeString);
static bool _IsTextPlaylist(const BString& mimeString);
static bool _IsBinaryPlaylist(const BString& mimeString);
static BString _MIMEString(const entry_ref* entry);
static void _AddPlayListFileToPlayList(const entry_ref& ref,
Playlist* playlist);
void _NotifyRefAdded(const entry_ref& ref,
int32 index) const;
void _NotifyRefRemoved(int32 index) const;
+146 -27
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2007, Haiku. All rights reserved.
* Copyright 2007-2008, Haiku. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -11,12 +11,17 @@
#include <stdio.h>
#include <Alert.h>
#include <Application.h>
#include <Autolock.h>
#include <Entry.h>
#include <File.h>
#include <Roster.h>
#include <Path.h>
#include <Menu.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <NodeInfo.h>
#include <ScrollBar.h>
#include <ScrollView.h>
#include <String.h>
@@ -25,6 +30,7 @@
#include <FilePanel.h>
#include "CommandStack.h"
#include "MainApp.h"
#include "PlaylistListView.h"
#include "RWLocker.h"
@@ -34,6 +40,7 @@ enum {
// file
M_PLAYLIST_OPEN = 'open',
M_PLAYLIST_SAVE = 'save',
M_PLAYLIST_SAVE_RESULT = 'psrs',
// edit
M_PLAYLIST_EMPTY = 'emty',
@@ -45,12 +52,11 @@ enum {
PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist,
Controller* controller)
: BWindow(frame, "Playlist", B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS)
, fOpenPanel(NULL)
, fSavePanel(NULL)
, fLocker(new RWLocker("command stack lock"))
, fCommandStack(new CommandStack(fLocker))
, fCommandStackListener(this)
B_ASYNCHRONOUS_CONTROLS),
fPlaylist(playlist),
fLocker(new RWLocker("command stack lock")),
fCommandStack(new CommandStack(fLocker)),
fCommandStackListener(this)
{
frame = Bounds();
@@ -89,9 +95,6 @@ PlaylistWindow::~PlaylistWindow()
fCommandStack->RemoveListener(&fCommandStackListener);
delete fCommandStack;
delete fLocker;
delete fOpenPanel;
delete fSavePanel;
}
@@ -138,20 +141,32 @@ PlaylistWindow::MessageReceived(BMessage* message)
break;
}
case M_PLAYLIST_SAVE:
if (!fSavePanel)
fSavePanel = new BFilePanel(B_SAVE_PANEL);
fSavePanel->Show();
case M_PLAYLIST_OPEN: {
BMessenger target(this);
BMessage result(B_REFS_RECEIVED);
BMessage appMessage(M_SHOW_OPEN_PANEL);
appMessage.AddMessenger("target", target);
appMessage.AddMessage("message", &result);
appMessage.AddString("title", "Open Playlist");
appMessage.AddString("label", "Open");
be_app->PostMessage(&appMessage);
break;
case B_SAVE_REQUESTED:
printf("We are saving\n");
//Use fListView and have a SaveToFile?
}
case M_PLAYLIST_SAVE: {
BMessenger target(this);
BMessage result(M_PLAYLIST_SAVE_RESULT);
BMessage appMessage(M_SHOW_SAVE_PANEL);
appMessage.AddMessenger("target", target);
appMessage.AddMessage("message", &result);
appMessage.AddString("title", "Save Playlist");
appMessage.AddString("label", "Save");
be_app->PostMessage(&appMessage);
break;
case M_PLAYLIST_OPEN:
if (!fOpenPanel)
fOpenPanel = new BFilePanel(B_OPEN_PANEL);
fOpenPanel->Show();
}
case M_PLAYLIST_SAVE_RESULT: {
_SavePlaylist(message);
break;
}
case M_PLAYLIST_EMPTY:
fListView->RemoveAll();
@@ -177,11 +192,11 @@ PlaylistWindow::_CreateMenu(BRect& frame)
BMenuBar* menuBar = new BMenuBar(frame, "main menu");
BMenu* fileMenu = new BMenu("Playlist");
menuBar->AddItem(fileMenu);
// fileMenu->AddItem(new BMenuItem("Open"B_UTF8_ELLIPSIS,
// new BMessage(M_PLAYLIST_OPEN), 'O'));
// fileMenu->AddItem(new BMenuItem("Save"B_UTF8_ELLIPSIS,
// new BMessage(M_PLAYLIST_SAVE), 'S'));
// fileMenu->AddSeparatorItem();
fileMenu->AddItem(new BMenuItem("Open"B_UTF8_ELLIPSIS,
new BMessage(M_PLAYLIST_OPEN), 'O'));
fileMenu->AddItem(new BMenuItem("Save"B_UTF8_ELLIPSIS,
new BMessage(M_PLAYLIST_SAVE), 'S'));
fileMenu->AddSeparatorItem();
fileMenu->AddItem(new BMenuItem("Close",
new BMessage(B_QUIT_REQUESTED), 'W'));
@@ -207,7 +222,6 @@ PlaylistWindow::_CreateMenu(BRect& frame)
}
// _ObjectChanged
void
PlaylistWindow::_ObjectChanged(const Notifier* object)
{
@@ -230,3 +244,108 @@ PlaylistWindow::_ObjectChanged(const Notifier* object)
}
}
static void
display_save_alert(const char* message)
{
BAlert* alert = new BAlert("Save Error", message, "Ok", NULL, NULL,
B_WIDTH_AS_USUAL, B_STOP_ALERT);
alert->Go(NULL);
}
static void
display_save_alert(status_t error)
{
BString errorMessage("Saving the playlist failed.\n\nError: ");
errorMessage << strerror(error);
display_save_alert(errorMessage.String());
}
void
PlaylistWindow::_SavePlaylist(const BMessage* message)
{
entry_ref ref;
const char* name;
if (message->FindRef("directory", &ref) != B_OK
|| message->FindString("name", &name) != B_OK) {
display_save_alert("Internal error (malformed message). "
"Saving the Playlist failed.");
return;
}
BString tempName(name);
tempName << system_time();
BPath origPath(&ref);
BPath tempPath(&ref);
if (origPath.InitCheck() != B_OK || tempPath.InitCheck() != B_OK
|| origPath.Append(name) != B_OK
|| tempPath.Append(tempName.String()) != B_OK) {
display_save_alert("Internal error (out of memory). "
"Saving the Playlist failed.");
return;
}
BEntry origEntry(origPath.Path());
BEntry tempEntry(tempPath.Path());
if (origEntry.InitCheck() != B_OK || tempEntry.InitCheck() != B_OK) {
display_save_alert("Internal error (out of memory). "
"Saving the Playlist failed.");
return;
}
class TempEntryRemover {
public:
TempEntryRemover(BEntry* entry)
: fEntry(entry)
{
}
~TempEntryRemover()
{
if (fEntry)
fEntry->Remove();
}
void Detach()
{
fEntry = NULL;
}
private:
BEntry* fEntry;
} remover(&tempEntry);
BFile file(&tempEntry, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
if (file.InitCheck() != B_OK) {
BString errorMessage("Saving the playlist failed:\n\nError: ");
errorMessage << strerror(file.InitCheck());
display_save_alert(errorMessage.String());
return;
}
AutoLocker<Playlist> lock(fPlaylist);
if (!lock.IsLocked()) {
display_save_alert("Internal error (locking failed). "
"Saving the Playlist failed.");
return;
}
status_t ret = fPlaylist->Flatten(&file);
if (ret != B_OK) {
display_save_alert(ret);
return;
}
lock.Unlock();
if (origEntry.Exists()) {
// TODO: copy attributes
}
// clobber original entry, if it exists
tempEntry.Rename(name, true);
remover.Detach();
BNodeInfo info(&file);
info.SetType("application/x-vnd.haiku-playlist");
}
@@ -39,6 +39,7 @@ class PlaylistWindow : public BWindow {
private:
void _CreateMenu(BRect& frame);
void _ObjectChanged(const Notifier* object);
void _SavePlaylist(const BMessage* message);
Playlist* fPlaylist;
PlaylistListView* fListView;
@@ -47,9 +48,6 @@ class PlaylistWindow : public BWindow {
BMenuItem* fUndoMI;
BMenuItem* fRedoMI;
BFilePanel* fOpenPanel;
BFilePanel* fSavePanel;
RWLocker* fLocker;
CommandStack* fCommandStack;
ListenerAdapter fCommandStackListener;
@@ -20,7 +20,6 @@
#ifdef __HAIKU__
# include <GridLayoutBuilder.h>
# include <GroupLayout.h>
# include <GroupLayoutBuilder.h>
# include <SpaceLayoutItem.h>
#endif