1 /* 2 * Copyright © 2009 Stephan Aßmus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT license. 4 */ 5 6 #include "FilePlaylistItem.h" 7 8 #include <stdio.h> 9 10 #include <new> 11 12 #include <Directory.h> 13 #include <File.h> 14 #include <FindDirectory.h> 15 #include <MediaFile.h> 16 #include <Path.h> 17 18 19 static const char* kPathKey = "path"; 20 21 22 FilePlaylistItem::FilePlaylistItem(const entry_ref& ref) 23 : 24 fRef(ref), 25 fNameInTrash("") 26 { 27 } 28 29 30 FilePlaylistItem::FilePlaylistItem(const FilePlaylistItem& other) 31 : 32 fRef(other.fRef), 33 fNameInTrash(other.fNameInTrash) 34 { 35 } 36 37 38 FilePlaylistItem::FilePlaylistItem(const BMessage* archive) 39 : 40 fRef(), 41 fNameInTrash("") 42 { 43 const char* path; 44 if (archive != NULL && archive->FindString(kPathKey, &path) == B_OK) { 45 if (get_ref_for_path(path, &fRef) != B_OK) 46 fRef = entry_ref(); 47 } 48 } 49 50 51 FilePlaylistItem::~FilePlaylistItem() 52 { 53 } 54 55 56 PlaylistItem* 57 FilePlaylistItem::Clone() const 58 { 59 return new (std::nothrow) FilePlaylistItem(*this); 60 } 61 62 63 BArchivable* 64 FilePlaylistItem::Instantiate(BMessage* archive) 65 { 66 if (validate_instantiation(archive, "FilePlaylistItem")) 67 return new (std::nothrow) FilePlaylistItem(archive); 68 69 return NULL; 70 } 71 72 73 // #pragma mark - 74 75 76 status_t 77 FilePlaylistItem::Archive(BMessage* into, bool deep) const 78 { 79 status_t ret = BArchivable::Archive(into, deep); 80 if (ret != B_OK) 81 return ret; 82 BPath path(&fRef); 83 ret = path.InitCheck(); 84 if (ret == B_OK) 85 ret = into->AddString(kPathKey, path.Path()); 86 return ret; 87 } 88 89 90 status_t 91 FilePlaylistItem::SetAttribute(const Attribute& attribute, 92 const BString& string) 93 { 94 return B_NOT_SUPPORTED; 95 } 96 97 98 status_t 99 FilePlaylistItem::GetAttribute(const Attribute& attribute, 100 BString& string) const 101 { 102 if (attribute == ATTR_STRING_NAME) { 103 string = fRef.name; 104 return B_OK; 105 } 106 return B_NOT_SUPPORTED; 107 } 108 109 110 status_t 111 FilePlaylistItem::SetAttribute(const Attribute& attribute, 112 const int32& value) 113 { 114 return B_NOT_SUPPORTED; 115 } 116 117 118 status_t 119 FilePlaylistItem::GetAttribute(const Attribute& attribute, 120 int32& value) const 121 { 122 return B_NOT_SUPPORTED; 123 } 124 125 126 status_t 127 FilePlaylistItem::SetAttribute(const Attribute& attribute, 128 const int64& value) 129 { 130 return B_NOT_SUPPORTED; 131 } 132 133 134 status_t 135 FilePlaylistItem::GetAttribute(const Attribute& attribute, 136 int64& value) const 137 { 138 return B_NOT_SUPPORTED; 139 } 140 141 142 // #pragma mark - 143 144 145 BString 146 FilePlaylistItem::LocationURI() const 147 { 148 BPath path(&fRef); 149 BString locationURI("file://"); 150 locationURI << path.Path(); 151 return locationURI; 152 } 153 154 155 status_t 156 FilePlaylistItem::GetIcon(BBitmap* bitmap, icon_size iconSize) const 157 { 158 BNode node(&fRef); 159 BNodeInfo info(&node); 160 return info.GetTrackerIcon(bitmap, iconSize); 161 } 162 163 164 status_t 165 FilePlaylistItem::MoveIntoTrash() 166 { 167 if (fNameInTrash.Length() != 0) { 168 // Already in the trash! 169 return B_ERROR; 170 } 171 172 char trashPath[B_PATH_NAME_LENGTH]; 173 status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device, 174 true /*create it*/, trashPath, B_PATH_NAME_LENGTH); 175 if (err != B_OK) { 176 fprintf(stderr, "failed to find Trash: %s\n", strerror(err)); 177 return err; 178 } 179 180 BEntry entry(&fRef); 181 err = entry.InitCheck(); 182 if (err != B_OK) { 183 fprintf(stderr, "failed to init BEntry for %s: %s\n", 184 fRef.name, strerror(err)); 185 return err; 186 } 187 BDirectory trashDir(trashPath); 188 if (err != B_OK) { 189 fprintf(stderr, "failed to init BDirectory for %s: %s\n", 190 trashPath, strerror(err)); 191 return err; 192 } 193 194 // Find a unique name for the entry in the trash 195 fNameInTrash = fRef.name; 196 int32 uniqueNameIndex = 1; 197 while (true) { 198 BEntry test(&trashDir, fNameInTrash.String()); 199 if (!test.Exists()) 200 break; 201 fNameInTrash = fRef.name; 202 fNameInTrash << ' ' << uniqueNameIndex; 203 uniqueNameIndex++; 204 } 205 206 // Remember the original path 207 BPath originalPath; 208 entry.GetPath(&originalPath); 209 210 // Finally, move the entry into the trash 211 err = entry.MoveTo(&trashDir, fNameInTrash.String()); 212 if (err != B_OK) { 213 fprintf(stderr, "failed to move entry into trash %s: %s\n", 214 trashPath, strerror(err)); 215 return err; 216 } 217 218 // Allow Tracker to restore this entry 219 BNode node(&entry); 220 BString originalPathString(originalPath.Path()); 221 node.WriteAttrString("_trk/original_path", &originalPathString); 222 223 return err; 224 } 225 226 227 228 status_t 229 FilePlaylistItem::RestoreFromTrash() 230 { 231 if (fNameInTrash.Length() <= 0) { 232 // Not in the trash! 233 return B_ERROR; 234 } 235 236 char trashPath[B_PATH_NAME_LENGTH]; 237 status_t err = find_directory(B_TRASH_DIRECTORY, fRef.device, 238 false /*create it*/, trashPath, B_PATH_NAME_LENGTH); 239 if (err != B_OK) { 240 fprintf(stderr, "failed to find Trash: %s\n", strerror(err)); 241 return err; 242 } 243 // construct the entry to the file in the trash 244 // TODO: BEntry(const BDirectory* directory, const char* path) is broken! 245 // BEntry entry(trashPath, fNamesInTrash[i].String()); 246 BPath path(trashPath, fNameInTrash.String()); 247 BEntry entry(path.Path()); 248 err = entry.InitCheck(); 249 if (err != B_OK) { 250 fprintf(stderr, "failed to init BEntry for %s: %s\n", 251 fNameInTrash.String(), strerror(err)); 252 return err; 253 } 254 //entry.GetPath(&path); 255 //printf("moving '%s'\n", path.Path()); 256 257 // construct the folder of the original entry_ref 258 node_ref nodeRef; 259 nodeRef.device = fRef.device; 260 nodeRef.node = fRef.directory; 261 BDirectory originalDir(&nodeRef); 262 err = originalDir.InitCheck(); 263 if (err != B_OK) { 264 fprintf(stderr, "failed to init original BDirectory for " 265 "%s: %s\n", fRef.name, strerror(err)); 266 return err; 267 } 268 269 //path.SetTo(&originalDir, fItems[i].name); 270 //printf("as '%s'\n", path.Path()); 271 272 // Reset the name here, the user may have already moved the entry 273 // out of the trash via Tracker for example. 274 fNameInTrash = ""; 275 276 // Finally, move the entry back into the original folder 277 err = entry.MoveTo(&originalDir, fRef.name); 278 if (err != B_OK) { 279 fprintf(stderr, "failed to restore entry from trash " 280 "%s: %s\n", fRef.name, strerror(err)); 281 return err; 282 } 283 284 // Remove the attribute that helps Tracker restore the entry. 285 BNode node(&entry); 286 node.RemoveAttr("_trk/original_path"); 287 288 return err; 289 } 290 291 292 // #pragma mark - 293 294 295 BMediaFile* 296 FilePlaylistItem::CreateMediaFile() const 297 { 298 return new (std::nothrow) BMediaFile(&fRef); 299 } 300 301