Changeset 12673


Ignore:
Timestamp:
Aug 13, 2011, 1:58:35 PM (10 years ago)
Author:
jordan
Message:

(trunk gtk) simplify the gtk+ client's watchdir code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/tr-core.c

    r12659 r12673  
    7070    GFileMonitor * monitor;
    7171    gulong         monitor_tag;
    72     char         * monitor_dir;
     72    GFile        * monitor_dir;
    7373    GSList       * monitor_files;
    7474    guint          monitor_idle_tag;
     
    554554***/
    555555
    556 struct watchdir_file
    557 {
    558     char * filename;
     556static time_t
     557get_file_mtime( GFile * file )
     558{
    559559    time_t mtime;
    560 };
    561 
    562 static int
    563 compare_watchdir_file_to_filename( const void * a, const void * filename )
    564 {
    565     return strcmp( ((const struct watchdir_file*)a)->filename, filename );
    566 }
    567 
    568 static time_t
    569 get_file_mtime( const char * filename )
    570 {
    571     time_t mtime;
    572     GFile * gfile = g_file_new_for_path( filename );
    573     GFileInfo * info = g_file_query_info( gfile, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, NULL, NULL );
     560    GFileInfo * info = g_file_query_info( file, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, NULL, NULL );
    574561    mtime = g_file_info_get_attribute_uint64( info, G_FILE_ATTRIBUTE_TIME_MODIFIED );
    575562    g_object_unref( G_OBJECT( info ) );
    576     g_object_unref( G_OBJECT( gfile ) );
    577563    return mtime;
    578 }
    579 
    580 static struct watchdir_file*
    581 watchdir_file_new( const char * filename )
    582 {
    583     struct watchdir_file * f;
    584     f = g_new( struct watchdir_file, 1 );
    585     f->filename = g_strdup( filename );
    586     f->mtime = get_file_mtime( filename );
    587     return f;
    588 }
    589 
    590 static void
    591 watchdir_file_free( struct watchdir_file * f )
    592 {
    593     g_free( f->filename );
    594     g_free( f );
    595564}
    596565
     
    599568{
    600569    GSList * l;
    601     GSList * addme = NULL;
    602     GSList * monitor_files = NULL;
     570    GSList * changing = NULL;
     571    GSList * unchanging = NULL;
    603572    TrCore * core = TR_CORE( gcore );
    604573    const time_t now = tr_time( );
    605574    struct TrCorePrivate * p = core->priv;
    606     const gboolean do_start = gtr_pref_flag_get( TR_PREFS_KEY_START );
    607     const gboolean do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
    608 
    609     /* of the monitor_files, make a list of those that haven't
    610      * changed lately, since they should be ready to add */
    611     for( l=p->monitor_files; l!=NULL; l=l->next ) {
    612         struct watchdir_file * f = l->data;
    613         f->mtime = get_file_mtime( f->filename );
    614         if( f->mtime + 2 >= now )
    615             monitor_files = g_slist_prepend( monitor_files, f );
    616         else {
    617             addme = g_slist_prepend( addme, g_file_new_for_commandline_arg( f->filename ) );
    618             watchdir_file_free( f );
    619         }
    620     }
    621 
    622     /* add the torrents from that list */
    623     core->priv->adding_from_watch_dir = TRUE;
    624     gtr_core_add_files( core, addme, do_start, do_prompt, TRUE );
    625     g_slist_foreach( addme, (GFunc)g_object_unref, NULL );
    626     g_slist_free( addme );
    627     core->priv->adding_from_watch_dir = FALSE;
    628 
    629     /* update the monitor_files list */
     575
     576    /* separate the files into two lists: changing and unchanging */
     577    for( l=p->monitor_files; l!=NULL; l=l->next )
     578    {
     579        GFile * file = l->data;
     580        const time_t mtime = get_file_mtime( file );
     581        if( mtime + 2 >= now )
     582            changing = g_slist_prepend( changing, file );
     583        else
     584            unchanging = g_slist_prepend( unchanging, file );
     585    }
     586
     587    /* add the files that have stopped changing */
     588    if( unchanging != NULL )
     589    {
     590        const gboolean do_start = gtr_pref_flag_get( TR_PREFS_KEY_START );
     591        const gboolean do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
     592
     593        core->priv->adding_from_watch_dir = TRUE;
     594        gtr_core_add_files( core, unchanging, do_start, do_prompt, TRUE );
     595        g_slist_foreach( unchanging, (GFunc)g_object_unref, NULL );
     596        g_slist_free( unchanging );
     597        core->priv->adding_from_watch_dir = FALSE;
     598    }
     599
     600    /* keep monitoring the ones that are still changing */
    630601    g_slist_free( p->monitor_files );
    631     p->monitor_files = monitor_files;
     602    p->monitor_files = changing;
    632603
    633604    /* if monitor_files is nonempty, keep checking every second */
     
    639610}
    640611
    641 static void
    642 core_watchdir_monitor_file( TrCore * core, const char * filename )
    643 {
    644     const gboolean isTorrent = g_str_has_suffix( filename, ".torrent" );
    645 
    646     if( isTorrent )
    647     {
     612/* If this file is a torrent, add it to our list */
     613static void
     614core_watchdir_monitor_file( TrCore * core, GFile * file )
     615{
     616    char * filename = g_file_get_path( file );
     617    const gboolean is_torrent = g_str_has_suffix( filename, ".torrent" );
     618
     619    if( is_torrent )
     620    {
     621        GSList * l;
    648622        struct TrCorePrivate * p = core->priv;
    649623
    650         if( !g_slist_find_custom( p->monitor_files, filename, (GCompareFunc)compare_watchdir_file_to_filename ) )
    651             p->monitor_files = g_slist_append( p->monitor_files, watchdir_file_new( filename ) );
    652 
    653         if( !p->monitor_idle_tag )
    654             p->monitor_idle_tag = gdk_threads_add_timeout_seconds( 1, core_watchdir_idle, core );
    655     }
    656 }
    657 
     624        /* if we're not already watching this file, start watching it now */
     625        for( l=p->monitor_files; l!=NULL; l=l->next )
     626            if( g_file_equal( file, l->data ) )
     627                break;
     628        if( l == NULL ) {
     629            g_object_ref( file );
     630            p->monitor_files = g_slist_prepend( p->monitor_files, file );
     631            if( p->monitor_idle_tag == 0 )
     632                p->monitor_idle_tag = gdk_threads_add_timeout_seconds( 1, core_watchdir_idle, core );
     633        }
     634    }
     635
     636    g_free( filename );
     637}
     638
     639/* GFileMonitor noticed a file was created */
    658640static void
    659641on_file_changed_in_watchdir( GFileMonitor       * monitor UNUSED,
     
    664646{
    665647    if( event_type == G_FILE_MONITOR_EVENT_CREATED )
    666     {
    667         char * filename = g_file_get_path( file );
    668         core_watchdir_monitor_file( core, filename );
    669         g_free( filename );
    670     }
    671 }
    672 
     648        core_watchdir_monitor_file( core, file );
     649}
     650
     651/* walk through the pre-existing files in the watchdir */
    673652static void
    674653core_watchdir_scan( TrCore * core )
    675654{
     655    const char * dirname = gtr_pref_string_get( PREF_KEY_DIR_WATCH );
     656    GDir * dir = g_dir_open( dirname, 0, NULL );
     657
     658    if( dir != NULL )
     659    {
     660        const char * name;
     661        while(( name = g_dir_read_name( dir )))
     662        {
     663            char * filename = g_build_filename( dirname, name, NULL );
     664            GFile * file = g_file_new_for_path( filename );
     665            core_watchdir_monitor_file( core, file );
     666            g_object_unref( file );
     667            g_free( filename );
     668        }
     669
     670        g_dir_close( dir );
     671    }
     672}
     673
     674static void
     675core_watchdir_update( TrCore * core )
     676{
    676677    const gboolean is_enabled = gtr_pref_flag_get( PREF_KEY_DIR_WATCH_ENABLED );
    677 
    678     if( is_enabled )
    679     {
    680         const char * dirname = gtr_pref_string_get( PREF_KEY_DIR_WATCH );
    681         GDir * dir = g_dir_open( dirname, 0, NULL );
    682 
    683         if( dir != NULL )
    684         {
    685             const char * basename;
    686             while(( basename = g_dir_read_name( dir )))
    687             {
    688                 char * filename = g_build_filename( dirname, basename, NULL );
    689                 core_watchdir_monitor_file( core, filename );
    690                 g_free( filename );
    691             }
    692 
    693             g_dir_close( dir );
    694         }
    695     }
    696 }
    697 
    698 static void
    699 core_watchdir_update( TrCore * core )
    700 {
    701     const char * dir = gtr_pref_string_get( PREF_KEY_DIR_WATCH );
    702     const gboolean is_enabled = gtr_pref_flag_get( PREF_KEY_DIR_WATCH_ENABLED );
    703     struct TrCorePrivate * p = TR_CORE( core )->priv;
    704 
    705     if( p->monitor && ( !is_enabled || tr_strcmp0( dir, p->monitor_dir ) ) )
     678    GFile * dir = g_file_new_for_path( gtr_pref_string_get( PREF_KEY_DIR_WATCH ) );
     679    struct TrCorePrivate * p = core->priv;
     680
     681    if( p->monitor && ( !is_enabled || !g_file_equal( dir, p->monitor_dir ) ) )
    706682    {
    707683        g_signal_handler_disconnect( p->monitor, p->monitor_tag );
    708         g_free( p->monitor_dir );
    709684        g_file_monitor_cancel( p->monitor );
    710         g_object_unref( G_OBJECT( p->monitor ) );
     685        g_object_unref( p->monitor );
     686        g_object_unref( p->monitor_dir );
     687
    711688        p->monitor_dir = NULL;
    712689        p->monitor = NULL;
     
    716693    if( is_enabled && !p->monitor )
    717694    {
    718         GFile * file = g_file_new_for_path( dir );
    719         GFileMonitor * m = g_file_monitor_directory( file, 0, NULL, NULL );
     695        GFileMonitor * m = g_file_monitor_directory( dir, 0, NULL, NULL );
    720696        core_watchdir_scan( core );
     697
     698        g_object_ref( dir );
    721699        p->monitor = m;
    722         p->monitor_dir = g_strdup( dir );
     700        p->monitor_dir = dir;
    723701        p->monitor_tag = g_signal_connect( m, "changed",
    724702                                           G_CALLBACK( on_file_changed_in_watchdir ), core );
    725703    }
     704
     705    g_object_unref( dir );
    726706}
    727707
Note: See TracChangeset for help on using the changeset viewer.