diff --git a/src/apps/mediaplayer/MainApp.cpp b/src/apps/mediaplayer/MainApp.cpp index a5aef1e7d6..f6d1d59697 100644 --- a/src/apps/mediaplayer/MainApp.cpp +++ b/src/apps/mediaplayer/MainApp.cpp @@ -2,7 +2,7 @@ * MainApp.cpp - Media Player for the Haiku Operating System * * Copyright (C) 2006 Marcus Overhagen - * Copyright (C) 2008 Stephan Aßmus + * Copyright (C) 2008 Stephan Aßmus (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 #include #include +#include #include #include #include @@ -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 diff --git a/src/apps/mediaplayer/MainApp.h b/src/apps/mediaplayer/MainApp.h index 5b2142b23a..c3219f883f 100644 --- a/src/apps/mediaplayer/MainApp.h +++ b/src/apps/mediaplayer/MainApp.h @@ -22,18 +22,36 @@ #define __MAIN_APP_H #include +#include + #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; }; diff --git a/src/apps/mediaplayer/MainWin.cpp b/src/apps/mediaplayer/MainWin.cpp index d775d4d002..17dc388fb1 100644 --- a/src/apps/mediaplayer/MainWin.cpp +++ b/src/apps/mediaplayer/MainWin.cpp @@ -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; diff --git a/src/apps/mediaplayer/MainWin.h b/src/apps/mediaplayer/MainWin.h index aa14dd7d30..88f0fc68a8 100644 --- a/src/apps/mediaplayer/MainWin.h +++ b/src/apps/mediaplayer/MainWin.h @@ -25,7 +25,6 @@ #include #include #include -#include #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; diff --git a/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp b/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp index c1e7a26103..b2fb21d28e 100644 --- a/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp +++ b/src/apps/mediaplayer/playlist/ImportPLItemsCommand.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #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) diff --git a/src/apps/mediaplayer/playlist/Playlist.cpp b/src/apps/mediaplayer/playlist/Playlist.cpp index 762802cb34..2dd56a0cc1 100644 --- a/src/apps/mediaplayer/playlist/Playlist.cpp +++ b/src/apps/mediaplayer/playlist/Playlist.cpp @@ -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; } diff --git a/src/apps/mediaplayer/playlist/Playlist.h b/src/apps/mediaplayer/playlist/Playlist.h index daa971e92d..94b072cc71 100644 --- a/src/apps/mediaplayer/playlist/Playlist.h +++ b/src/apps/mediaplayer/playlist/Playlist.h @@ -26,6 +26,7 @@ #include #include +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; diff --git a/src/apps/mediaplayer/playlist/PlaylistWindow.cpp b/src/apps/mediaplayer/playlist/PlaylistWindow.cpp index af7f680027..0d42ff583c 100644 --- a/src/apps/mediaplayer/playlist/PlaylistWindow.cpp +++ b/src/apps/mediaplayer/playlist/PlaylistWindow.cpp @@ -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 +#include #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -25,6 +30,7 @@ #include #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 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"); +} + diff --git a/src/apps/mediaplayer/playlist/PlaylistWindow.h b/src/apps/mediaplayer/playlist/PlaylistWindow.h index 45694f01dd..bd20534c05 100644 --- a/src/apps/mediaplayer/playlist/PlaylistWindow.h +++ b/src/apps/mediaplayer/playlist/PlaylistWindow.h @@ -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; diff --git a/src/apps/mediaplayer/settings/SettingsWindow.cpp b/src/apps/mediaplayer/settings/SettingsWindow.cpp index cb7faf55e3..a05bd6a49e 100644 --- a/src/apps/mediaplayer/settings/SettingsWindow.cpp +++ b/src/apps/mediaplayer/settings/SettingsWindow.cpp @@ -20,7 +20,6 @@ #ifdef __HAIKU__ # include -# include # include # include #endif