mirror of
https://github.com/transmission/transmission
synced 2025-02-21 21:57:01 +00:00
Update 2005-11-21
This commit is contained in:
parent
aad7bf22cb
commit
23ef3653e3
22 changed files with 403 additions and 85 deletions
20
AUTHORS
20
AUTHORS
|
@ -1,7 +1,19 @@
|
|||
Authors:
|
||||
AUTHORS for Transmission <http://transmission.m0k.org/>
|
||||
=======================================================
|
||||
|
||||
Transmission is written is maintained by:
|
||||
|
||||
Eric Petit <titer@m0k.org>
|
||||
+ About everything until now
|
||||
+ Back-end
|
||||
+ OS X interface
|
||||
|
||||
Josh Elsasser <josh@elsasser.org>
|
||||
+ GTK interface
|
||||
|
||||
Michael Demars <keul@m0k.org>
|
||||
+ OS X interface
|
||||
+ Growl notifications
|
||||
+ AppleScript support
|
||||
|
||||
|
||||
Thanks to:
|
||||
|
@ -15,10 +27,6 @@ Mike Matas <http://www.mikematas.com/>
|
|||
Omar and Adrien
|
||||
+ Beta testing
|
||||
|
||||
Michael Demars
|
||||
+ Beta testing
|
||||
+ OS X UI patches
|
||||
|
||||
Various people
|
||||
+ Writing http://wiki.theory.org/BitTorrentSpecification
|
||||
|
||||
|
|
2
Jamfile
2
Jamfile
|
@ -6,6 +6,7 @@ ObjectHdrs transmissioncli.c : $(TOP)/libtransmission ;
|
|||
|
||||
if $(OS) = MACOSX
|
||||
{
|
||||
OSXLinks macosx/Frameworks/Growl.framework/Growl ;
|
||||
OSXInfoPlist macosx/Info.plist : macosx/Info.plist.in ;
|
||||
OSXBundle Transmission.app : libtransmission.a
|
||||
macosx/Controller.h
|
||||
|
@ -15,6 +16,7 @@ if $(OS) = MACOSX
|
|||
macosx/English.lproj/MainMenu.nib/classes.nib
|
||||
macosx/English.lproj/MainMenu.nib/info.nib
|
||||
macosx/English.lproj/MainMenu.nib/keyedobjects.nib
|
||||
macosx/Frameworks/Growl.framework/Growl
|
||||
macosx/Images/Info.png
|
||||
macosx/Images/Open.png
|
||||
macosx/Images/PauseOff.png
|
||||
|
|
19
Jamrules
19
Jamrules
|
@ -16,6 +16,12 @@ DEFINES += VERSION_MAJOR=$(VERSION_MAJOR)
|
|||
OPTIM = -O3 ;
|
||||
RM = rm -Rf ;
|
||||
|
||||
rule SystemLibraries
|
||||
{
|
||||
LINKLIBS on [ FAppendSuffix $(<) : $(SUFEXE) ] ?= $(LINKLIBS) ;
|
||||
LINKLIBS on [ FAppendSuffix $(<) : $(SUFEXE) ] += $(>) ;
|
||||
}
|
||||
|
||||
if $(OS) = MACOSX
|
||||
{
|
||||
# Build universal binaries
|
||||
|
@ -34,6 +40,18 @@ if $(OS) = MACOSX
|
|||
libtool -static $(>) -o $(<) ;
|
||||
}
|
||||
|
||||
rule OSXLinks
|
||||
{
|
||||
}
|
||||
actions OSXLinks
|
||||
{
|
||||
( cd macosx/Frameworks/Growl.framework/ && \
|
||||
ln -s Versions/Current/Growl && \
|
||||
ln -s Versions/Current/Headers && \
|
||||
ln -s Versions/Current/Resources && \
|
||||
ln -s A Versions/Current )
|
||||
}
|
||||
|
||||
rule OSXInfoPlist
|
||||
{
|
||||
Depends $(1) : $(2) ;
|
||||
|
@ -73,6 +91,7 @@ if $(OS) = MACOSX
|
|||
ditto AUTHORS "$TMP/AUTHORS.txt" &&
|
||||
ditto LICENSE "$TMP/LICENSE.txt" &&
|
||||
ditto NEWS "$TMP/NEWS.txt" &&
|
||||
strip -S "$TMP/Transmission.app/Contents/MacOS/Transmission" &&
|
||||
( echo "[InternetShortcut]"; \
|
||||
echo "URL=http://transmission.m0k.org/" ) > \
|
||||
"$TMP/Homepage.url" &&
|
||||
|
|
48
configure
vendored
48
configure
vendored
|
@ -45,24 +45,30 @@ EOF
|
|||
|
||||
gtk_test()
|
||||
{
|
||||
cat > testconf.c << EOF
|
||||
#include <gtk/gtk.h>
|
||||
int main()
|
||||
{
|
||||
gtk_main();
|
||||
}
|
||||
EOF
|
||||
if $CC `pkg-config gtk+-2.0 --cflags --libs 2>/dev/null` -o testconf testconf.c
|
||||
if pkg-config gtk+-2.0 > /dev/null 2>&1
|
||||
then
|
||||
echo "GTK+: yes"
|
||||
GTK=yes
|
||||
GTKCCFLAGS=`pkg-config gtk+-2.0 --cflags`
|
||||
GTKLINKLIBS=`pkg-config gtk+-2.0 --libs`
|
||||
cat > testconf.c << EOF
|
||||
#include <gtk/gtk.h>
|
||||
int main()
|
||||
{
|
||||
gtk_main();
|
||||
}
|
||||
EOF
|
||||
if $CC `pkg-config gtk+-2.0 --cflags --libs` -o testconf testconf.c > /dev/null 2>&1
|
||||
then
|
||||
echo "GTK+: yes"
|
||||
GTK=yes
|
||||
GTKCCFLAGS=`pkg-config gtk+-2.0 --cflags`
|
||||
GTKLINKLIBS=`pkg-config gtk+-2.0 --libs`
|
||||
else
|
||||
echo "GTK+: no"
|
||||
GTK=no
|
||||
fi
|
||||
rm -f testconf.c testconf
|
||||
else
|
||||
echo "GTK+: no"
|
||||
echo "GTK+: no"
|
||||
GTK=no
|
||||
fi
|
||||
rm -f testconf.c testconf
|
||||
}
|
||||
|
||||
#
|
||||
|
@ -155,18 +161,6 @@ case $SYSTEM in
|
|||
esac
|
||||
echo "System: $SYSTEM"
|
||||
|
||||
# Check for GTK
|
||||
if pkg-config gtk+-2.0
|
||||
then
|
||||
echo "GTK+: yes"
|
||||
GTK=yes
|
||||
GTKCCFLAGS=`pkg-config gtk+-2.0 --cflags`
|
||||
GTKLINKLIBS=`pkg-config gtk+-2.0 --libs`
|
||||
else
|
||||
echo "GTK+: no"
|
||||
GTK=no
|
||||
fi
|
||||
|
||||
#
|
||||
# OpenSSL settings
|
||||
#
|
||||
|
@ -180,7 +174,7 @@ fi
|
|||
# GTK settings
|
||||
#
|
||||
if [ ${gtk_disable} = 1 ]; then
|
||||
echo "GTK+: no"
|
||||
echo "GTK+: no"
|
||||
else
|
||||
gtk_test
|
||||
fi
|
||||
|
|
19
gtk/Jamfile
19
gtk/Jamfile
|
@ -1,15 +1,10 @@
|
|||
{
|
||||
SubDir TOP gtk ;
|
||||
SubDir TOP gtk ;
|
||||
|
||||
GTK_SRC = conf.c main.c util.c ;
|
||||
GTK_SRC = conf.c main.c util.c ;
|
||||
|
||||
local CCFLAGS = $(CCFLAGS) $(GTKCCFLAGS) ;
|
||||
#local LINKLIBS = $(LINKLIBS) $(GTKLINKLIBS) ;
|
||||
local HDRS = $(HDRS) $(TOP)/libtransmission ;
|
||||
Main transmission-gtk : $(GTK_SRC) ;
|
||||
LinkLibraries transmission-gtk : libtransmission.a ;
|
||||
|
||||
# jesus fucking christ, I give up
|
||||
LINKLIBS += $(GTKLINKLIBS) ;
|
||||
|
||||
Main transmission-gtk : $(GTK_SRC) ;
|
||||
LinkLibraries transmission-gtk : libtransmission.a ;
|
||||
}
|
||||
ObjectCcFlags $(GTK_SRC) : $(GTKCCFLAGS) ;
|
||||
ObjectHdrs $(GTK_SRC) : $(TOP)/libtransmission ;
|
||||
SystemLibraries transmission-gtk : $(GTKLINKLIBS) ;
|
||||
|
|
|
@ -127,6 +127,7 @@ struct tr_torrent_s
|
|||
tr_fd_t * fdlimit;
|
||||
|
||||
int status;
|
||||
int finished;
|
||||
char error[128];
|
||||
|
||||
char * id;
|
||||
|
|
|
@ -41,7 +41,7 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
|
|||
int i;
|
||||
struct stat sb;
|
||||
|
||||
snprintf( inf->torrent, MAX_PATH_LENGTH, path );
|
||||
snprintf( inf->torrent, MAX_PATH_LENGTH, "%s", path );
|
||||
|
||||
if( stat( path, &sb ) )
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ int tr_metainfoParse( tr_info_t * inf, const char * path )
|
|||
tr_bencFree( &meta );
|
||||
return 1;
|
||||
}
|
||||
snprintf( inf->trackerAnnounce, MAX_PATH_LENGTH, s2 );
|
||||
snprintf( inf->trackerAnnounce, MAX_PATH_LENGTH, "%s", s2 );
|
||||
|
||||
/* Piece length */
|
||||
if( !( val = tr_bencDictFind( beInfo, "piece length" ) ) )
|
||||
|
|
|
@ -358,7 +358,7 @@ static void recvAnswer( tr_tracker_t * tc )
|
|||
tr_err( "Tracker: %s", bePeers->val.s.s );
|
||||
tor->status |= TR_TRACKER_ERROR;
|
||||
snprintf( tor->error, sizeof( tor->error ),
|
||||
bePeers->val.s.s );
|
||||
"%s", bePeers->val.s.s );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -606,3 +606,21 @@ int tr_trackerScrape( tr_torrent_t * tor, int * seeders, int * leechers )
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tr_trackerSeeders( tr_torrent_t * tor)
|
||||
{
|
||||
if (tor->status != TR_STATUS_PAUSE)
|
||||
{
|
||||
return (tor->tracker)->seeders;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tr_trackerLeechers( tr_torrent_t * tor)
|
||||
{
|
||||
if (tor->status != TR_STATUS_PAUSE)
|
||||
{
|
||||
return (tor->tracker)->leechers;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -31,6 +31,20 @@ void tr_trackerCompleted ( tr_tracker_t * );
|
|||
void tr_trackerStopped ( tr_tracker_t * );
|
||||
void tr_trackerClose ( tr_tracker_t * );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_trackerSeeders
|
||||
***********************************************************************
|
||||
* Looks for the seeders/leechers as returned by the tracker.
|
||||
**********************************************************************/
|
||||
int tr_trackerSeeders ( tr_torrent_t * );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_trackerLeechers
|
||||
***********************************************************************
|
||||
* Looks for the seeders/leechers as returned by the tracker.
|
||||
**********************************************************************/
|
||||
int tr_trackerLeechers ( tr_torrent_t * );
|
||||
|
||||
int tr_trackerScrape ( tr_torrent_t *, int *, int * );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -172,6 +172,8 @@ int tr_torrentInit( tr_handle_t * h, const char * path )
|
|||
tor->status = TR_STATUS_PAUSE;
|
||||
tor->id = h->id;
|
||||
tor->key = h->key;
|
||||
tor->finished = 0;
|
||||
|
||||
|
||||
/* Guess scrape URL */
|
||||
s1 = strchr( inf->trackerAnnounce, '/' );
|
||||
|
@ -317,6 +319,15 @@ int tr_torrentCount( tr_handle_t * h )
|
|||
return h->torrentCount;
|
||||
}
|
||||
|
||||
int tr_getFinished( tr_handle_t * h, int i)
|
||||
{
|
||||
return h->torrents[i]->finished;
|
||||
}
|
||||
void tr_setFinished( tr_handle_t * h, int i, int val)
|
||||
{
|
||||
h->torrents[i]->finished = val;
|
||||
}
|
||||
|
||||
int tr_torrentStat( tr_handle_t * h, tr_stat_t ** stat )
|
||||
{
|
||||
tr_stat_t * s;
|
||||
|
@ -374,6 +385,9 @@ int tr_torrentStat( tr_handle_t * h, tr_stat_t ** stat )
|
|||
s[i].progress = tr_cpCompletionAsFloat( tor->completion );
|
||||
s[i].rateDownload = rateDownload( tor );
|
||||
s[i].rateUpload = rateUpload( tor );
|
||||
|
||||
s[i].seeders = tr_trackerSeeders(tor);
|
||||
s[i].leechers = tr_trackerLeechers(tor);
|
||||
|
||||
if( s[i].rateDownload < 0.1 )
|
||||
{
|
||||
|
@ -496,6 +510,7 @@ static void downloadLoop( void * _tor )
|
|||
{
|
||||
/* Done */
|
||||
tor->status = TR_STATUS_SEED;
|
||||
tor->finished = 1;
|
||||
tr_trackerCompleted( tor->tracker );
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,20 @@ void tr_setUploadLimit( tr_handle_t *, int );
|
|||
**********************************************************************/
|
||||
void tr_torrentRates( tr_handle_t *, float *, float * );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_getFinished
|
||||
***********************************************************************
|
||||
* Tests to see if torrent is finished
|
||||
**********************************************************************/
|
||||
int tr_getFinished( tr_handle_t *, int );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_setFinished
|
||||
***********************************************************************
|
||||
* Sets the boolean value finished in the torrent back to false
|
||||
**********************************************************************/
|
||||
void tr_setFinished( tr_handle_t *, int, int );
|
||||
|
||||
/***********************************************************************
|
||||
* tr_torrentInit
|
||||
***********************************************************************
|
||||
|
@ -205,6 +219,8 @@ struct tr_stat_s
|
|||
int peersUploading;
|
||||
int peersDownloading;
|
||||
char pieces[120];
|
||||
int seeders;
|
||||
int leechers;
|
||||
|
||||
uint64_t downloaded;
|
||||
uint64_t uploaded;
|
||||
|
|
|
@ -26,10 +26,11 @@
|
|||
#include <Cocoa/Cocoa.h>
|
||||
#include <transmission.h>
|
||||
#include "PrefsController.h"
|
||||
#include <Growl/Growl.h>
|
||||
|
||||
@class TorrentTableView;
|
||||
|
||||
@interface Controller : NSObject
|
||||
@interface Controller : NSObject <GrowlApplicationBridgeDelegate>
|
||||
{
|
||||
tr_handle_t * fHandle;
|
||||
int fCount;
|
||||
|
@ -43,6 +44,7 @@
|
|||
IBOutlet NSMenuItem * fAdvancedBarItem;
|
||||
IBOutlet NSMenuItem * fPauseResumeItem;
|
||||
IBOutlet NSMenuItem * fRemoveItem;
|
||||
IBOutlet NSMenuItem * fRevealItem;
|
||||
|
||||
IBOutlet NSWindow * fWindow;
|
||||
IBOutlet TorrentTableView * fTableView;
|
||||
|
@ -57,6 +59,8 @@
|
|||
IBOutlet NSTextField * fInfoSize;
|
||||
IBOutlet NSTextField * fInfoPieces;
|
||||
IBOutlet NSTextField * fInfoPieceSize;
|
||||
IBOutlet NSTextField * fInfoSeeders;
|
||||
IBOutlet NSTextField * fInfoLeechers;
|
||||
IBOutlet NSTextField * fInfoFolder;
|
||||
IBOutlet NSTextField * fInfoDownloaded;
|
||||
IBOutlet NSTextField * fInfoUploaded;
|
||||
|
@ -71,8 +75,10 @@
|
|||
- (void) openSheetClosed: (NSOpenPanel *) s returnCode: (int) code
|
||||
contextInfo: (void *) info;
|
||||
- (void) stopTorrent: (id) sender;
|
||||
- (void) stopAllTorrents: (id) sender;
|
||||
- (void) stopTorrentWithIndex: (int) index;
|
||||
- (void) resumeTorrent: (id) sender;
|
||||
- (void) resumeAllTorrents: (id) sender;
|
||||
- (void) resumeTorrentWithIndex: (int) index;
|
||||
- (void) removeTorrent: (id) sender;
|
||||
- (void) removeTorrentDeleteFile: (id) sender;
|
||||
|
@ -92,6 +98,8 @@
|
|||
- (void) showMainWindow: (id) sender;
|
||||
- (void) linkHomepage: (id) sender;
|
||||
- (void) linkForums: (id) sender;
|
||||
- (void) notifyGrowl: (NSString *) file folder: (NSString *) folder;
|
||||
- (void) revealInFinder: (NSString *) path;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -77,8 +77,12 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
[fPauseResumeItem setAction: NULL];
|
||||
if( row < 0 )
|
||||
{
|
||||
[fRevealItem setAction: NULL];
|
||||
return;
|
||||
}
|
||||
|
||||
[fRevealItem setAction: @selector( revealFromMenu: )];
|
||||
|
||||
if( fStat[row].status & TR_STATUS_PAUSE )
|
||||
{
|
||||
[fPauseResumeItem setTitle: @"Resume"];
|
||||
|
@ -185,7 +189,10 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Register with the growl system */
|
||||
[GrowlApplicationBridge setGrowlDelegate:self];
|
||||
|
||||
/* Update the interface every 500 ms */
|
||||
fCount = 0;
|
||||
fStat = NULL;
|
||||
|
@ -358,6 +365,15 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
[fAdvancedBarItem setState: NSOnState];
|
||||
[defaults setObject:@"YES" forKey:@"UseAdvancedBar"];
|
||||
}
|
||||
[fTableView display];
|
||||
}
|
||||
|
||||
/* called on by applescript */
|
||||
- (void) open: (NSArray *) files
|
||||
{
|
||||
fFilenames = [files retain];
|
||||
[self performSelectorOnMainThread: @selector(cantFindAName:)
|
||||
withObject: NULL waitUntilDone: NO];
|
||||
}
|
||||
|
||||
- (void) openShowSheet: (id) sender
|
||||
|
@ -403,6 +419,19 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
[self resumeTorrentWithIndex: [fTableView selectedRow]];
|
||||
}
|
||||
|
||||
- (void) resumeAllTorrents: (id) sender
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < fCount; i++)
|
||||
{
|
||||
if ( fStat[i].status & ( TR_STATUS_STOPPING
|
||||
| TR_STATUS_PAUSE | TR_STATUS_STOPPED ) )
|
||||
{
|
||||
[self resumeTorrentWithIndex: i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) resumeTorrentWithIndex: (int) idx
|
||||
{
|
||||
tr_torrentStart( fHandle, idx );
|
||||
|
@ -414,6 +443,19 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
[self stopTorrentWithIndex: [fTableView selectedRow]];
|
||||
}
|
||||
|
||||
- (void) stopAllTorrents: (id) sender
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < fCount; i++)
|
||||
{
|
||||
if ( fStat[i].status & ( TR_STATUS_CHECK
|
||||
| TR_STATUS_DOWNLOAD | TR_STATUS_SEED) )
|
||||
{
|
||||
[self stopTorrentWithIndex: i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) stopTorrentWithIndex: (int) idx
|
||||
{
|
||||
tr_torrentStop( fHandle, idx );
|
||||
|
@ -434,33 +476,33 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
{
|
||||
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
|
||||
|
||||
[alert addButtonWithTitle:@"No"];
|
||||
[alert addButtonWithTitle:@"Yes"];
|
||||
[alert addButtonWithTitle:@"Delete"];
|
||||
[alert addButtonWithTitle:@"Cancel"];
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
[alert setMessageText:@"Are you sure you want to remove and delete?"];
|
||||
[alert setMessageText:@"Do you want to remove this torrent from Transmission?"];
|
||||
|
||||
if ( (deleteTorrent && torrentWarning) &&
|
||||
!( dataWarning && deleteData ) )
|
||||
{
|
||||
/* delete torrent warning YES, delete data warning NO */
|
||||
[alert setInformativeText:@"If you choose yes, the .torrent file will "
|
||||
"be deleted. This cannot be undone."];
|
||||
[alert setInformativeText:@"This will delete the .torrent file only. "
|
||||
"This can not be undone!"];
|
||||
}
|
||||
else if( (deleteData && dataWarning) &&
|
||||
!( torrentWarning && deleteTorrent ) )
|
||||
{
|
||||
/* delete torrent warning NO, delete data warning YES */
|
||||
[alert setInformativeText:@"If you choose yes, the downloaded data will "
|
||||
"be deleted. This cannot be undone."];
|
||||
[alert setInformativeText:@"This will delete the downloaded data. "
|
||||
"This can not be undone!"];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* delete torrent warning YES, delete data warning YES */
|
||||
[alert setInformativeText:@"If you choose yes, both downloaded data and "
|
||||
"torrent file will be deleted. This cannot be undone."];
|
||||
[alert setInformativeText:@"This will delete the downloaded data and "
|
||||
".torrent file. This can not be undone!"];
|
||||
}
|
||||
|
||||
if ( [alert runModal] == NSAlertFirstButtonReturn )
|
||||
if ( [alert runModal] == NSAlertSecondButtonReturn )
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -534,7 +576,7 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
- (void) updateUI: (NSTimer *) t
|
||||
{
|
||||
float dl, ul;
|
||||
int row;
|
||||
int row, i;
|
||||
|
||||
/* Update the NSTableView */
|
||||
if( fStat )
|
||||
|
@ -560,6 +602,19 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
[fInfoUploaded setStringValue:
|
||||
stringForFileSize( fStat[row].uploaded )];
|
||||
}
|
||||
|
||||
/* check if torrents have recently ended. */
|
||||
for (i = 0; i < fCount; i++)
|
||||
{
|
||||
if( !tr_getFinished( fHandle, i ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
[self notifyGrowl: [NSString stringWithUTF8String:
|
||||
fStat[i].info.name] folder: [NSString stringWithUTF8String:
|
||||
fStat[i].folder]];
|
||||
tr_setFinished( fHandle, i, 0 );
|
||||
}
|
||||
|
||||
/* Must we do this? Can't remember */
|
||||
[self updateBars];
|
||||
|
@ -575,8 +630,9 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
|
||||
int status = fStat[idx].status;
|
||||
|
||||
NSMenuItem *pauseItem = [fContextMenu itemWithTag: CONTEXT_PAUSE];
|
||||
NSMenuItem *pauseItem = [fContextMenu itemWithTag: CONTEXT_PAUSE];
|
||||
NSMenuItem *removeItem = [fContextMenu itemAtIndex: 1];
|
||||
NSMenuItem *infoItem = [fContextMenu itemAtIndex: 2];
|
||||
|
||||
[pauseItem setTarget: self];
|
||||
|
||||
|
@ -599,6 +655,13 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
[pauseItem setEnabled: NO];
|
||||
}
|
||||
|
||||
if( [fInfoPanel isVisible] )
|
||||
{
|
||||
[infoItem setTitle: @"Hide Info"];
|
||||
} else {
|
||||
[infoItem setTitle: @"Show Info"];
|
||||
}
|
||||
|
||||
return fContextMenu;
|
||||
}
|
||||
|
||||
|
@ -668,6 +731,8 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
[fInfoFolder setStringValue: @""];
|
||||
[fInfoDownloaded setStringValue: @""];
|
||||
[fInfoUploaded setStringValue: @""];
|
||||
[fInfoSeeders setStringValue: @""];
|
||||
[fInfoLeechers setStringValue: @""];
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -686,6 +751,19 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
stringForFileSize( fStat[row].info.pieceSize )];
|
||||
[fInfoFolder setStringValue: [[NSString stringWithUTF8String:
|
||||
tr_torrentGetFolder( fHandle, row )] lastPathComponent]];
|
||||
|
||||
if ( fStat[row].seeders == -1 ) {
|
||||
[fInfoSeeders setStringValue: [NSString stringWithUTF8String: "?"]];
|
||||
} else {
|
||||
[fInfoSeeders setStringValue: [NSString stringWithFormat: @"%d",
|
||||
fStat[row].seeders]];
|
||||
}
|
||||
if ( fStat[row].leechers == -1 ) {
|
||||
[fInfoLeechers setStringValue: [NSString stringWithUTF8String: "?"]];
|
||||
} else {
|
||||
[fInfoLeechers setStringValue: [NSString stringWithFormat: @"%d",
|
||||
fStat[row].leechers]];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSToolbarItem *) toolbar: (NSToolbar *) t itemForItemIdentifier:
|
||||
|
@ -805,7 +883,7 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
|
||||
rectWin = [fWindow frame];
|
||||
rectView = [[fWindow contentView] frame];
|
||||
foo = 68.0 + MAX( 1, tr_torrentCount( fHandle ) ) * 62.0 -
|
||||
foo = 47.0 + MAX( 1, tr_torrentCount( fHandle ) ) * 62.0 -
|
||||
rectView.size.height;
|
||||
|
||||
rectWin.size.height += foo;
|
||||
|
@ -831,4 +909,67 @@ static void sleepCallBack( void * controller, io_service_t y,
|
|||
URLWithString:@"http://transmission.m0k.org/forum/"]];
|
||||
}
|
||||
|
||||
- (void) notifyGrowl: (NSString * ) file folder: (NSString *) folder
|
||||
{
|
||||
[GrowlApplicationBridge
|
||||
notifyWithTitle: @"Download complete."
|
||||
description: [NSString stringWithFormat: @"Seeding: %@", file]
|
||||
notificationName: @"Download complete."
|
||||
iconData: nil
|
||||
priority: 0
|
||||
isSticky: FALSE
|
||||
clickContext: [NSString stringWithFormat: @"%@/%@", folder, file]];
|
||||
}
|
||||
|
||||
- (NSDictionary *)registrationDictionaryForGrowl
|
||||
{
|
||||
NSString *title = [NSString stringWithUTF8String: "Download complete."];
|
||||
NSMutableArray *defNotesArray = [NSMutableArray array];
|
||||
NSMutableArray *allNotesArray = [NSMutableArray array];
|
||||
|
||||
[allNotesArray addObject:title];
|
||||
[defNotesArray addObject:[NSNumber numberWithUnsignedInt:0]];
|
||||
|
||||
NSDictionary *regDict = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"Transmission", GROWL_APP_NAME,
|
||||
allNotesArray, GROWL_NOTIFICATIONS_ALL,
|
||||
defNotesArray, GROWL_NOTIFICATIONS_DEFAULT,
|
||||
nil];
|
||||
|
||||
return regDict;
|
||||
}
|
||||
|
||||
- (NSString *) applicationNameForGrowl
|
||||
{
|
||||
return [NSString stringWithUTF8String: "Transmission"];
|
||||
}
|
||||
|
||||
- (void) growlNotificationWasClicked: (id) clickContext
|
||||
{
|
||||
[self revealInFinder: (NSString *) clickContext];
|
||||
}
|
||||
|
||||
- (void) revealFromMenu: (id) sender
|
||||
{
|
||||
[fTableView revealInFinder: [fTableView selectedRow]];
|
||||
}
|
||||
|
||||
- (void) revealInFinder: (NSString *) path
|
||||
{
|
||||
NSString * string;
|
||||
NSAppleScript * appleScript;
|
||||
NSDictionary * error;
|
||||
|
||||
string = [NSString stringWithFormat: @"tell application "
|
||||
"\"Finder\"\nactivate\nreveal (POSIX file \"%@\")\nend tell",
|
||||
path];
|
||||
appleScript = [[NSAppleScript alloc] initWithSource: string];
|
||||
if( ![appleScript executeAndReturnError: &error] )
|
||||
{
|
||||
printf( "Reveal in Finder: AppleScript failed\n" );
|
||||
}
|
||||
[appleScript release];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
6
macosx/English.lproj/MainMenu.nib/classes.nib
generated
6
macosx/English.lproj/MainMenu.nib/classes.nib
generated
|
@ -10,9 +10,12 @@
|
|||
removeTorrentDeleteBoth = id;
|
||||
removeTorrentDeleteData = id;
|
||||
removeTorrentDeleteFile = id;
|
||||
resumeAllTorrents = id;
|
||||
resumeTorrent = id;
|
||||
revealFromMenu = id;
|
||||
showInfo = id;
|
||||
showMainWindow = id;
|
||||
stopAllTorrents = id;
|
||||
stopTorrent = id;
|
||||
};
|
||||
CLASS = Controller;
|
||||
|
@ -23,9 +26,11 @@
|
|||
fInfoAnnounce = NSTextField;
|
||||
fInfoDownloaded = NSTextField;
|
||||
fInfoFolder = NSTextField;
|
||||
fInfoLeechers = NSTextField;
|
||||
fInfoPanel = NSPanel;
|
||||
fInfoPieceSize = NSTextField;
|
||||
fInfoPieces = NSTextField;
|
||||
fInfoSeeders = NSTextField;
|
||||
fInfoSize = NSTextField;
|
||||
fInfoTitle = NSTextField;
|
||||
fInfoTracker = NSTextField;
|
||||
|
@ -33,6 +38,7 @@
|
|||
fPauseResumeItem = NSMenuItem;
|
||||
fPrefsController = PrefsController;
|
||||
fRemoveItem = NSMenuItem;
|
||||
fRevealItem = NSMenuItem;
|
||||
fTableView = TorrentTableView;
|
||||
fTotalDLField = NSTextField;
|
||||
fTotalULField = NSTextField;
|
||||
|
|
10
macosx/English.lproj/MainMenu.nib/info.nib
generated
10
macosx/English.lproj/MainMenu.nib/info.nib
generated
|
@ -3,13 +3,13 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>185 138 361 432 0 0 1280 832 </string>
|
||||
<string>231 62 361 432 0 0 1280 832 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>29</key>
|
||||
<string>105 768 371 44 0 0 1280 832 </string>
|
||||
<string>92 769 371 44 0 0 1280 832 </string>
|
||||
<key>456</key>
|
||||
<string>174 512 147 87 0 0 1280 832 </string>
|
||||
<string>116 510 147 106 0 0 1280 832 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>443.0</string>
|
||||
|
@ -17,8 +17,10 @@
|
|||
<integer>3</integer>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>29</integer>
|
||||
<integer>456</integer>
|
||||
<integer>29</integer>
|
||||
<integer>21</integer>
|
||||
<integer>273</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>8F46</string>
|
||||
|
|
BIN
macosx/English.lproj/MainMenu.nib/keyedobjects.nib
generated
BIN
macosx/English.lproj/MainMenu.nib/keyedobjects.nib
generated
Binary file not shown.
|
@ -41,5 +41,7 @@
|
|||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<string>YES</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
NSString * fUlString;
|
||||
|
||||
NSBitmapImageRep * fBgBmp;
|
||||
NSImage * fImg;
|
||||
NSBitmapImageRep * fBmp;
|
||||
}
|
||||
- (id) init;
|
||||
|
|
|
@ -84,7 +84,6 @@ static uint32_t kGreen[] =
|
|||
bgImg = [NSImage imageNamed: @"Progress.png"];
|
||||
fBgBmp = [[bgImg representations] objectAtIndex: 0];
|
||||
size = [bgImg size];
|
||||
fImg = [[NSImage alloc] initWithSize: size];
|
||||
fBmp = [[NSBitmapImageRep alloc]
|
||||
initWithBitmapDataPlanes: NULL pixelsWide: size.width
|
||||
pixelsHigh: size.height bitsPerSample: 8 samplesPerPixel: 4
|
||||
|
@ -92,8 +91,6 @@ static uint32_t kGreen[] =
|
|||
colorSpaceName: NSCalibratedRGBColorSpace
|
||||
bytesPerRow: 0 bitsPerPixel: 0];
|
||||
|
||||
[fImg addRepresentation: fBmp];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -110,11 +107,11 @@ static uint32_t kGreen[] =
|
|||
fUlString = [NSString stringWithFormat:
|
||||
@"UL: %.2f KB/s", fStat->rateUpload];
|
||||
|
||||
for( i = 0; i < [fImg size].height; i++ )
|
||||
for( i = 0; i < [fBmp size].height; i++ )
|
||||
{
|
||||
memcpy( [fBmp bitmapData] + i * [fBmp bytesPerRow],
|
||||
[fBgBmp bitmapData] + i * [fBgBmp bytesPerRow],
|
||||
[fImg size].width * 4 );
|
||||
[fBmp size].width * 4 );
|
||||
}
|
||||
|
||||
if( [[NSUserDefaults standardUserDefaults]
|
||||
|
@ -140,6 +137,11 @@ static uint32_t kGreen[] =
|
|||
|
||||
for( w = 0; w < 120; w++ )
|
||||
{
|
||||
if( w >= (int) ( fStat->progress * 120 ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if( fStat->status & TR_STATUS_SEED )
|
||||
{
|
||||
*p = kGreen[h];
|
||||
|
@ -148,12 +150,6 @@ static uint32_t kGreen[] =
|
|||
{
|
||||
*p = kBlue2[h];
|
||||
}
|
||||
|
||||
if( w >= (int) ( fStat->progress * 120 ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
@ -181,12 +177,11 @@ static uint32_t kGreen[] =
|
|||
if( h < 2 )
|
||||
{
|
||||
/* First two lines: dark blue to show progression */
|
||||
*p = kBlue4[h];
|
||||
|
||||
if( w >= (int) ( fStat->progress * 120 ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
*p = kBlue4[h];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -222,6 +217,8 @@ static uint32_t kGreen[] =
|
|||
|
||||
- (void) drawWithFrame: (NSRect) cellFrame inView: (NSView *) view
|
||||
{
|
||||
NSImage * img;
|
||||
|
||||
if( ![view lockFocusIfCanDraw] )
|
||||
{
|
||||
return;
|
||||
|
@ -236,9 +233,13 @@ static uint32_t kGreen[] =
|
|||
|
||||
pen.x += 5; pen.y += 5;
|
||||
|
||||
pen.y += [fImg size].height;
|
||||
[fImg compositeToPoint: pen operation: NSCompositeSourceOver];
|
||||
pen.y -= [fImg size].height;
|
||||
img = [[NSImage alloc] initWithSize: [fBmp size]];
|
||||
[img addRepresentation: fBmp];
|
||||
[img setFlipped: YES];
|
||||
[img drawAtPoint: pen fromRect:
|
||||
NSMakeRect( 0, 0, [fBmp size].width, [fBmp size].height )
|
||||
operation: NSCompositeSourceOver fraction: 1.0];
|
||||
[img release];
|
||||
|
||||
[attributes setObject: [NSFont messageFontOfSize:10.0]
|
||||
forKey: NSFontAttributeName];
|
||||
|
|
|
@ -106,9 +106,16 @@
|
|||
}
|
||||
else if( [self pointInRevealRect: point] )
|
||||
{
|
||||
[self revealInFinder: row];
|
||||
[fController revealInFinder: [NSString stringWithFormat:
|
||||
@"%@/%@", [NSString stringWithUTF8String: fStat[row].folder],
|
||||
[NSString stringWithUTF8String: fStat[row].info.name]]];
|
||||
[self display];
|
||||
}
|
||||
else if( row >= 0 && col == [self columnWithIdentifier: @"Progress"]
|
||||
&& ( [e modifierFlags] & NSAlternateKeyMask ) )
|
||||
{
|
||||
[fController advancedChanged: NULL];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self selectRowIndexes: [NSIndexSet indexSetWithIndex: row]
|
||||
|
|
47
macosx/Transmission.sdef
Normal file
47
macosx/Transmission.sdef
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
|
||||
<dictionary title="Transmission Terminology">
|
||||
<suite name="Standard Suite" code="????"
|
||||
description="Common classes and commands for all applications.">
|
||||
|
||||
|
||||
<command name="open" code="aevtodoc"
|
||||
description="Open a document.">
|
||||
<direct-parameter description="The file(s) to be opened.">
|
||||
<type type="file" list="yes"/>
|
||||
</direct-parameter>
|
||||
</command>
|
||||
|
||||
<command name="quit" code="aevtquit" description="Quit the application.">
|
||||
<cocoa class="NSQuitCommand"/>
|
||||
</command>
|
||||
|
||||
<class name="application" code="capp"
|
||||
description="The application's top-level scripting object.">
|
||||
<cocoa class="NSApplication"/>
|
||||
<property name="name" code="pnam" type="text" access="r"
|
||||
description="The name of the application."/>
|
||||
<property name="frontmost" code="pisf" type="boolean" access="r"
|
||||
description="Is this the frontmost (active) application?">
|
||||
<cocoa key="isActive"/>
|
||||
</property>
|
||||
<property name="version" code="vers" type="text" access="r"
|
||||
description="The version of the application."/>
|
||||
<element type="document" access="r">
|
||||
<cocoa key="orderedDocuments"/>
|
||||
</element>
|
||||
<element type="window" access="r">
|
||||
<cocoa key="orderedWindows"/>
|
||||
</element>
|
||||
<responds-to name="open">
|
||||
<cocoa method="handleOpenScriptCommand:"/>
|
||||
</responds-to>
|
||||
<responds-to name="print">
|
||||
<cocoa method="handlePrintScriptCommand:"/>
|
||||
</responds-to>
|
||||
<responds-to name="quit">
|
||||
<cocoa method="handleQuitScriptCommand:"/>
|
||||
</responds-to>
|
||||
</class>
|
||||
</suite>
|
||||
</dictionary>
|
|
@ -18,6 +18,8 @@
|
|||
4D6DAAC7090CE00500F43C22 /* RevealOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D6DAAC5090CE00500F43C22 /* RevealOn.png */; };
|
||||
4D752E930913C949008EAAD4 /* Preferences.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D752E920913C949008EAAD4 /* Preferences.png */; };
|
||||
4D813EB508AA43AC00191DB4 /* Progress.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D813EB408AA43AC00191DB4 /* Progress.png */; };
|
||||
4D81E2E4092EF0CB00F24127 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D81E2E3092EF0CB00F24127 /* Growl.framework */; };
|
||||
4D81E309092EF26F00F24127 /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4D81E2E3092EF0CB00F24127 /* Growl.framework */; };
|
||||
4DA6FDBA0911233800450CB1 /* PauseOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DA6FDB80911233800450CB1 /* PauseOn.png */; };
|
||||
4DA6FDBB0911233800450CB1 /* PauseOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DA6FDB90911233800450CB1 /* PauseOff.png */; };
|
||||
4DA6FDC5091141AD00450CB1 /* ResumeOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 4DA6FDC3091141AD00450CB1 /* ResumeOff.png */; };
|
||||
|
@ -60,6 +62,19 @@
|
|||
};
|
||||
/* End PBXBuildStyle section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
4D81E301092EF24500F24127 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
4D81E309092EF26F00F24127 /* Growl.framework in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
|
@ -84,6 +99,7 @@
|
|||
4D6DAAC5090CE00500F43C22 /* RevealOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = RevealOn.png; path = Images/RevealOn.png; sourceTree = "<group>"; };
|
||||
4D752E920913C949008EAAD4 /* Preferences.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Preferences.png; path = Images/Preferences.png; sourceTree = "<group>"; };
|
||||
4D813EB408AA43AC00191DB4 /* Progress.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Progress.png; path = Images/Progress.png; sourceTree = "<group>"; };
|
||||
4D81E2E3092EF0CB00F24127 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = Frameworks/Growl.framework; sourceTree = "<group>"; };
|
||||
4DA6FDB80911233800450CB1 /* PauseOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = PauseOn.png; path = Images/PauseOn.png; sourceTree = "<group>"; };
|
||||
4DA6FDB90911233800450CB1 /* PauseOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = PauseOff.png; path = Images/PauseOff.png; sourceTree = "<group>"; };
|
||||
4DA6FDC3091141AD00450CB1 /* ResumeOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ResumeOff.png; path = Images/ResumeOff.png; sourceTree = "<group>"; };
|
||||
|
@ -106,6 +122,7 @@
|
|||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
||||
4DF0C5AE08991C1600DD8943 /* libtransmission.a in Frameworks */,
|
||||
4D3EA0AA08AE13C600EA10C2 /* IOKit.framework in Frameworks */,
|
||||
4D81E2E4092EF0CB00F24127 /* Growl.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -133,6 +150,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
|
||||
4D81E2E3092EF0CB00F24127 /* Growl.framework */,
|
||||
);
|
||||
name = "Linked Frameworks";
|
||||
sourceTree = "<group>";
|
||||
|
@ -220,6 +238,7 @@
|
|||
8D1107290486CEB800E47090 /* Resources */,
|
||||
8D11072C0486CEB800E47090 /* Sources */,
|
||||
8D11072E0486CEB800E47090 /* Frameworks */,
|
||||
4D81E301092EF24500F24127 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -331,6 +350,10 @@
|
|||
ppc,
|
||||
i386,
|
||||
);
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(FRAMEWORK_SEARCH_PATHS)",
|
||||
"$(SRCROOT)/Frameworks",
|
||||
);
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 3;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
|
|
Loading…
Reference in a new issue