source: trunk/gtk/tr-torrent.c @ 5208

Last change on this file since 5208 was 5208, checked in by charles, 14 years ago

more i18n strings work

  • Property svn:keywords set to Date Rev Author Id
File size: 9.0 KB
Line 
1/******************************************************************************
2 * $Id: tr-torrent.c 5208 2008-03-06 21:59:00Z charles $
3 *
4 * Copyright (c) 2006-2008 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#include <string.h>
26#include <unistd.h>
27
28#include <gtk/gtk.h>
29#include <glib/gi18n.h>
30#include <glib/gstdio.h>
31
32#include <libtransmission/transmission.h>
33
34#include "tr-prefs.h"
35#include "tr-torrent.h"
36#include "conf.h"
37#include "notify.h"
38#include "util.h"
39
40struct TrTorrentPrivate
41{
42   tr_torrent * handle;
43   gboolean do_delete;
44   gboolean seeding_cap_enabled;
45   gdouble seeding_cap; /* ratio to stop seeding at */
46};
47
48
49static void
50tr_torrent_init(GTypeInstance *instance, gpointer g_class UNUSED )
51{
52    TrTorrent * self = TR_TORRENT( instance );
53    struct TrTorrentPrivate * p;
54
55    p = self->priv = G_TYPE_INSTANCE_GET_PRIVATE( self,
56                                                  TR_TORRENT_TYPE,
57                                                  struct TrTorrentPrivate );
58    p->handle = NULL;
59    p->seeding_cap = 2.0;
60
61#ifdef REFDBG
62    g_message( "torrent %p init", self );
63#endif
64}
65
66static int
67isDisposed( const TrTorrent * self )
68{
69    return !self || !self->priv;
70}
71
72static void
73tr_torrent_dispose( GObject * o )
74{
75    GObjectClass * parent;
76    TrTorrent * self = TR_TORRENT( o );
77
78    if( !isDisposed( self ) )
79    {
80        if( self->priv->handle )
81        {
82            if( self->priv->do_delete )
83                tr_torrentDelete( self->priv->handle );
84            else
85                tr_torrentClose( self->priv->handle );
86        }
87
88        self->priv = NULL;
89    }
90
91    parent = g_type_class_peek(g_type_parent(TR_TORRENT_TYPE));
92    parent->dispose( o );
93}
94
95static void
96tr_torrent_class_init( gpointer g_class, gpointer g_class_data UNUSED )
97{
98    GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
99    gobject_class->dispose = tr_torrent_dispose;
100    g_type_class_add_private( g_class, sizeof( struct TrTorrentPrivate ) );
101}
102
103GType
104tr_torrent_get_type( void )
105{
106  static GType type = 0;
107
108  if( !type )
109  {
110    static const GTypeInfo info = {
111      sizeof (TrTorrentClass),
112      NULL,   /* base_init */
113      NULL,   /* base_finalize */
114      tr_torrent_class_init,   /* class_init */
115      NULL,   /* class_finalize */
116      NULL,   /* class_data */
117      sizeof (TrTorrent),
118      0,      /* n_preallocs */
119      tr_torrent_init, /* instance_init */
120      NULL,
121    };
122    type = g_type_register_static(G_TYPE_OBJECT, "TrTorrent", &info, 0);
123  }
124  return type;
125}
126
127tr_torrent *
128tr_torrent_handle(TrTorrent *tor)
129{
130    g_assert( TR_IS_TORRENT(tor) );
131
132    return isDisposed( tor ) ? NULL : tor->priv->handle;
133}
134
135const tr_stat *
136tr_torrent_stat(TrTorrent *tor)
137{
138    tr_torrent * handle = tr_torrent_handle( tor );
139    return handle ? tr_torrentStatCached( handle ) : NULL;
140}
141
142const tr_info *
143tr_torrent_info( TrTorrent * tor )
144{
145    tr_torrent * handle = tr_torrent_handle( tor );
146    return handle ? tr_torrentInfo( handle ) : NULL;
147}
148
149void
150tr_torrent_start( TrTorrent * self )
151{
152    tr_torrent * handle = tr_torrent_handle( self );
153    if( handle )
154        tr_torrentStart( handle );
155}
156
157void
158tr_torrent_stop( TrTorrent * self )
159{
160    tr_torrent * handle = tr_torrent_handle( self );
161    if( handle )
162        tr_torrentStop( handle );
163}
164
165
166static gboolean
167notifyInMainThread( gpointer user_data )
168{
169    if( pref_flag_get( PREF_KEY_NOTIFY ) )
170        tr_notify_send( TR_TORRENT( user_data ) );
171    return FALSE;
172}
173static void
174statusChangedCallback( tr_torrent   * tor UNUSED,
175                       cp_status_t    status,
176                       void         * user_data )
177{
178    if( status == TR_CP_COMPLETE )
179        g_idle_add( notifyInMainThread, user_data );
180}
181static TrTorrent *
182maketorrent( tr_torrent * handle )
183{
184    TrTorrent * tor = g_object_new( TR_TORRENT_TYPE, NULL );
185    tor->priv->handle = handle;
186    tr_torrentSetStatusCallback( handle, statusChangedCallback, tor );
187    return tor;
188}
189
190TrTorrent*
191tr_torrent_new_preexisting( tr_torrent * tor )
192{
193    return maketorrent( tor );
194}
195
196TrTorrent *
197tr_torrent_new_ctor( tr_handle  * handle,
198                     tr_ctor    * ctor,
199                     char      ** err )
200{
201    tr_torrent * tor;
202    int errcode;
203
204    errcode = -1;
205    *err = NULL;
206
207    tor = tr_torrentNew( handle, ctor, &errcode );
208 
209    if( !tor )
210    {
211        const char * filename = tr_ctorGetSourceFile( ctor );
212        if( !filename )
213            filename = "(null)";
214
215        switch( errcode )
216        {
217            case TR_EINVALID:
218                *err = g_strdup_printf( _("%s: not a valid torrent file"), filename );
219                 break;
220            case TR_EDUPLICATE:
221                *err = g_strdup_printf( _("%s: torrent is already open"), filename );
222                break;
223            default:
224                *err = g_strdup( filename );
225                break;
226        }
227
228        return NULL;
229    }
230
231    return maketorrent( tor );
232}
233
234void
235tr_torrent_check_seeding_cap ( TrTorrent *gtor)
236{
237  const tr_stat * st = tr_torrent_stat( gtor );
238  if ((gtor->priv->seeding_cap_enabled) && (st->ratio >= gtor->priv->seeding_cap))
239    tr_torrent_stop (gtor);
240}
241void
242tr_torrent_set_seeding_cap_ratio ( TrTorrent *gtor, gdouble ratio )
243{
244  gtor->priv->seeding_cap = ratio;
245  tr_torrent_check_seeding_cap (gtor);
246}
247void
248tr_torrent_set_seeding_cap_enabled ( TrTorrent *gtor, gboolean b )
249{
250  if ((gtor->priv->seeding_cap_enabled = b))
251    tr_torrent_check_seeding_cap (gtor);
252}
253
254char *
255tr_torrent_status_str ( TrTorrent * gtor )
256{
257    char * top = 0;
258
259    const tr_stat * st = tr_torrent_stat( gtor );
260
261    const int tpeers = MAX (st->peersConnected, 0);
262    const int upeers = MAX (st->peersGettingFromUs, 0);
263    const int eta = st->eta;
264    double prog = st->percentDone * 100.0; /* [0...100] */
265
266    switch( st->status )
267    {
268        case TR_STATUS_CHECK_WAIT:
269            prog = st->recheckProgress * 100.0; /* [0...100] */
270            top = g_strdup_printf( _("Waiting to verify local data (%.1f%% tested)"), prog );
271            break;
272
273        case TR_STATUS_CHECK:
274            prog = st->recheckProgress * 100.0; /* [0...100] */
275            top = g_strdup_printf( _("Verifying local data (%.1f%% tested)"), prog );
276            break;
277
278        case TR_STATUS_DOWNLOAD:
279            if( eta < 0 )
280                top = g_strdup_printf( _("Stalled (%.1f%%)"), prog );
281            else {
282                char timestr[128];
283                tr_strltime( timestr, eta, sizeof( timestr ) );
284                top = g_strdup_printf( _("%s remaining (%.1f%%)"), timestr, prog );
285            }
286            break;
287
288        case TR_STATUS_DONE:
289            top = g_strdup_printf(
290                ngettext( "Uploading to %d of %d connected peer",
291                          "Uploading to %d of %d connected peers", tpeers ),
292                          upeers, tpeers );
293            break;
294
295        case TR_STATUS_SEED:
296            top = g_strdup_printf(
297                ngettext( "Seeding to %d of %d connected peer",
298                          "Seeding to %d of %d connected peers", tpeers ),
299                          upeers, tpeers );
300            break;
301
302        case TR_STATUS_STOPPED:
303            top = g_strdup_printf( _("Stopped (%.1f%%)"), prog );
304            break;
305
306        default:
307            top = g_strdup_printf( _("Unrecognized state: %d"), st->status );
308            break;
309
310    }
311
312    return top;
313}
314
315void
316tr_torrent_set_delete_flag( TrTorrent * gtor, gboolean do_delete )
317{
318    if( !isDisposed( gtor ) )
319        gtor->priv->do_delete = do_delete;
320}
321
322void
323tr_torrent_delete_files( TrTorrent * gtor )
324{
325    int i;
326    const tr_info * info = tr_torrent_info( gtor );
327    const char * stop = tr_torrentGetFolder( tr_torrent_handle( gtor ) );
328
329    for( i=0; info && i<info->fileCount; ++i )
330    {
331        char * file = g_build_filename( stop, info->files[i].name, NULL );
332        while( strcmp( stop, file ) && strlen(stop) < strlen(file) )
333        {
334            char * swap = g_path_get_dirname( file );
335            g_unlink( file );
336            g_free( file );
337            file = swap;
338        }
339        g_free( file );
340    }
341}
Note: See TracBrowser for help on using the repository browser.