source: trunk/beos/TRApplication.cpp @ 1125

Last change on this file since 1125 was 261, checked in by titer, 16 years ago

Updated svn:keywords

  • Property svn:keywords set to Date Rev Author Id
File size: 8.3 KB
Line 
1// $Id: TRApplication.cpp 261 2006-05-29 21:27:31Z livings124 $
2
3#include "TRApplication.h"
4
5#include <stdio.h>
6#include <string.h>
7#include <stdlib.h>
8
9#include <AppFileInfo.h>
10#include <Alert.h>
11#include <Bitmap.h>
12#include <File.h>
13#include <FindDirectory.h>
14#include <Messenger.h>
15#include <Mime.h>
16#include <Path.h>
17#include <String.h>
18#include <Resources.h>
19#include <Roster.h>
20
21int main(int argc, char** argv) {
22        TRApplication *app = new TRApplication();
23        if (app->InitCheck() == B_OK) {
24                app->Run();
25        } else {
26                BString errMsg("");
27                errMsg << "The following error occurred loading Transmission:\n"
28                       << strerror(app->InitCheck());
29                BAlert *ohNo = new BAlert("Transmission Error", 
30                        errMsg.String(),
31                        "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
32                ohNo->Go();
33        }
34        delete app;
35       
36        return (0);
37}
38
39
40TRApplication::TRApplication() : BApplication(APP_SIG) {
41        status_t err = B_OK;
42        torrentDir = NULL;
43       
44        // Install Mime types if necessary.
45        BMimeType torrentType("application/x-bittorrent");
46        if (torrentType.InitCheck() == B_OK) {
47                if (!torrentType.IsInstalled()) {
48                        fprintf(stderr, "Installing mime type...\n");
49                        // Icon
50                        app_info runningInfo;
51                        GetAppInfo(&runningInfo);
52                        BFile appFile(&(runningInfo.ref), B_READ_ONLY);
53                        BResources res(&appFile, false);
54                       
55                        size_t len = 0;
56                        BBitmap *icon = NULL;
57                        void *iconBits = NULL;
58                       
59                        iconBits = res.FindResource('ICON', "BEOS:L:application/x-bittorrent", &len);
60                        if (iconBits) {
61                                icon = new BBitmap(BRect(0, 0, 31, 31), B_CMAP8);
62                                icon->SetBits(iconBits, len, 0, B_CMAP8);
63                                torrentType.SetIcon(icon, B_LARGE_ICON);
64                                delete icon;
65                                icon = NULL;
66                                len = 0;
67                        }
68                       
69                        iconBits = res.FindResource('ICON', "BEOS:M:application/x-bittorrent", &len);
70                        if (iconBits) {
71                                icon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8);
72                                icon->SetBits(iconBits, len, 0, B_CMAP8);
73                                torrentType.SetIcon(icon, B_MINI_ICON);
74                                delete icon;
75                        }
76                       
77                        // Extensions
78                        BMessage extensions;
79                        extensions.AddString("extensions", "torrent");
80                        torrentType.SetFileExtensions(&extensions);
81                       
82                        torrentType.SetShortDescription("BitTorrent Meta File");
83                        torrentType.SetLongDescription("BitTorrent Protocol Meta File (http://www.bittorrent.com)");
84                       
85                        // Set Preferred Application
86                        torrentType.SetPreferredApp(APP_SIG, B_OPEN);
87                       
88                        torrentType.Install();
89                }
90        }
91       
92        // Create Settings folder and structure
93        BPath settingsPath;
94        err = find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath, false);
95        if (err == B_OK) {
96                BDirectory settings(settingsPath.Path());
97                BDirectory *trSettings = new BDirectory();
98               
99                err = settings.CreateDirectory("Transmission", trSettings);
100                if (err == B_FILE_EXISTS) {
101                        err = trSettings->SetTo(&settings, "Transmission");
102                }
103               
104                if (err == B_OK) {
105                        torrentDir = new BDirectory();
106                        err = trSettings->CreateDirectory("Torrents", torrentDir);
107                        if (err != B_OK) {
108                                torrentDir->SetTo(trSettings, "Torrents");
109                        }
110                }
111                delete trSettings;
112        }
113       
114        // Create window
115        window = new TRWindow();
116        window->RescanTorrents();
117        settings = new TRPrefsWindow();
118       
119        openPanel = new BFilePanel();
120        openPanel->SetRefFilter(new TRFilter());
121}
122
123
124TRApplication::~TRApplication() {
125        if (window->Lock()) {
126                window->Quit();
127        }
128        if (settings->Lock()) {
129                settings->Quit();
130        }
131       
132        if (openPanel != NULL) {
133                delete openPanel;
134        }
135       
136        if (torrentDir != NULL) {
137                delete torrentDir;
138        }
139}
140
141
142/**
143 * Checks to make sure our Settings directory structure is in place.
144 * If this fails, then we need to display an alert and vomit.
145 */
146status_t TRApplication::InitCheck() {
147        if (torrentDir != NULL) {
148                return torrentDir->InitCheck();
149        }
150        return B_ERROR;
151}
152
153
154void TRApplication::AboutRequested() {
155        // Read the application version info
156        app_info runningInfo;
157        GetAppInfo(&runningInfo);
158        BFile appFile(&(runningInfo.ref), B_READ_ONLY);
159        BAppFileInfo appInfo(&appFile);
160        version_info vInfo;
161        appInfo.GetVersionInfo(&vInfo, B_APP_VERSION_KIND);
162       
163        BString aboutMsg("");
164        aboutMsg << "Transmission\n"
165                 << "Version " << vInfo.major << "." << vInfo.middle << "." << vInfo.minor << "\n"
166                 << "Eric Petit & Bryan Varner\n";
167        BAlert *aboutBox = new BAlert("About Transmission", aboutMsg.String(), "Close");
168        aboutBox->Go();
169}
170
171
172void TRApplication::ReadyToRun() {
173        SetPulseRate(500000);
174        window->Show();
175}
176
177
178void TRApplication::Pulse() {
179        window->UpdateList(-1, false);
180}
181
182
183/**
184 * When a ref is received, we copy each file that is to be opened into
185 * B_USER_SETTINGS/Transmission/Torrents
186 *
187 * Our window node_monitors this folder for added / removed torrent meta files.
188 *
189 * Each copy is performed in a seperate thread to avoid blocking / locking the app.
190 */
191void TRApplication::RefsReceived(BMessage *message) {
192        int32 count;
193        type_code code;
194        message->GetInfo("refs", &code, &count);
195        for (int i = 0; i < count; i++) {
196                entry_ref *ref = (entry_ref*)calloc(sizeof(entry_ref), 1);
197                if (message->FindRef("refs", i, ref) == B_OK) {
198                        thread_id cp_thread = spawn_thread(TRApplication::Copy, "TorrentDuper",
199                                                           B_NORMAL_PRIORITY, (void *)ref);
200                        if (!((cp_thread) < B_OK)) {
201                                resume_thread(cp_thread);
202                        }
203                }
204        }
205}
206
207/**
208 * Needed for browsers or command line interaction
209 */
210void TRApplication::ArgvReceived(int32 _argc, char** _argv) 
211{
212        entry_ref ref;
213        BMessage refs(B_REFS_RECEIVED);
214        for( int32 i = 0; i < _argc; ++i )
215        {
216                if( B_OK == get_ref_for_path(_argv[i], &ref) )
217                {
218                        refs.AddRef("refs", &ref);
219                }
220        }
221       
222        be_app_messenger.SendMessage(refs);
223}
224
225/**
226 * BMessage handling.
227 */
228void TRApplication::MessageReceived(BMessage *message) {
229        BApplication::MessageReceived(message);
230        /*
231         * When the copy of a torrent file is complete, we get a message
232         * signaling that we should add the now copied .torrent file to our Transfer Window.
233         */
234        if (message->what == TR_ADD) {
235                // Add the torrent to the window.
236                entry_ref torrentRef;
237                if (message->FindRef("torrent", &torrentRef) == B_OK) {
238                        BEntry *entry = new BEntry(&torrentRef, true);
239                        window->AddEntry(entry);
240                        delete entry;
241                }
242        /* Show the Open Dialog */
243        } else if (message->what == TR_OPEN) {
244                openPanel->Show();
245        } else if (message->what == TR_SETTINGS) {
246                settings->MoveTo(window->Frame().left + (window->Frame().Width() - settings->Frame().Width()) / 2, 
247                                 window->Frame().top + (window->Frame().Height() - settings->Frame().Height()) / 2);
248                       
249                settings->Show();
250        } else if (message->what == TR_RELOAD_SETTINGS) {
251                window->LoadSettings();
252        }
253}
254
255bool TRApplication::QuitRequested() {
256        return BApplication::QuitRequested();
257}
258
259/**
260 * Thread Function.
261 * The thread copies the original .torrent file into the torrents folder,
262 * then signals the window to load the torrent meta info from the copy.
263 * The torrent window will then node_monitor the file so that if it's removed
264 * the torrent will cease.
265 *
266 * Keeping the file copy in a separate thread keeps us from blocking up the
267 * rest of our program.
268 *
269 * This behavior lets us kill the original .torrent download from disc (which
270 * speaking as a user I have a tendency to do) but keep the meta around for
271 * Transmission to use later.
272 *
273 * If the user whacks the .torrent file from our settings folder, then we'll
274 * remove it from the list (node_monitor!) and if they remove it from our list
275 * we'll remove it from the file system.
276 */
277int32 TRApplication::Copy(void *data) {
278        entry_ref *ref = (entry_ref*)data;
279       
280        BFile source(ref, B_READ_ONLY);
281        BFile target(((TRApplication*)be_app)->TorrentDir(), ref->name, 
282                     B_WRITE_ONLY | B_CREATE_FILE | B_FAIL_IF_EXISTS);
283       
284        BEntry targetEntry(((TRApplication*)be_app)->TorrentDir(), ref->name);
285        entry_ref targetRef;
286        targetEntry.GetRef(&targetRef);
287       
288        // Only perform the copy if the target is freshly created. Everything is B_OK!
289        if (source.InitCheck() == B_OK && target.InitCheck() == B_OK) {
290                if (target.Lock() == B_OK) {
291                        char *buffer = (char*)calloc(1, 4096); // 4k data buffer.
292                        ssize_t read = 0;
293                        while ((read = source.Read(buffer, 4096)) > 0) {
294                                target.Write(buffer, read);
295                        }
296                        free(buffer);
297                        target.Unlock();
298                }
299        }
300       
301        BMessage msg(TR_ADD);
302        msg.AddRef("torrent", &targetRef);
303        BMessenger messenger(be_app);
304        messenger.SendMessage(&msg);
305       
306        free(ref);
307        return B_OK;
308}
309
310/**
311 * Filters the FilePanel for torrent files and directories.
312 */
313bool TRFilter::Filter(const entry_ref *ref, BNode *node, struct stat *st, const char *mimetype) {
314        return (node->IsDirectory() || 
315           (strcmp(mimetype, "application/x-bittorrent") == 0) ||
316           (strstr(ref->name, ".torrent") != NULL));
317
318}
Note: See TracBrowser for help on using the repository browser.