xref: /haiku/src/apps/mediaplayer/playlist/FilePlaylistItem.cpp (revision a1163de83ea633463a79de234b8742ee106531b2)
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