Changeset 6b0d4285f439b7b2bba24c8e948da63cf92f6c1a

Show
Ignore:
Timestamp:
04/09/05 01:44:25 (3 years ago)
Author:
Gildas Bazin <gbazin@videolan.org>
git-committer:
Gildas Bazin <gbazin@videolan.org> 1125791065 +0000
git-parent:

[37a65fa65e9e5f16f38a964d5696efde91f479f8]

git-author:
Gildas Bazin <gbazin@videolan.org> 1125791065 +0000
Message:

* modules/access_filter/timeshift.c: complete rewrite. Configurable granularity so it doesn't waste as much disk space + deals with full disk by overwritting oldest data.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/access_filter/timeshift.c

    rfe087a3 r6b0d428  
    11/***************************************************************************** 
    2  * timeshift.c 
     2 * timeshift.c: access filter implementing timeshifting capabilities 
    33 ***************************************************************************** 
    44 * Copyright (C) 2005 the VideoLAN team 
    5  * $Id: demux.c 7546 2004-04-29 13:53:29Z gbazin $ 
    6  * 
    7  * Author: Laurent Aimar <fenrir@via.ecp.fr> 
     5 * $Id$ 
     6 * 
     7 * Authors: Laurent Aimar <fenrir@via.ecp.fr> 
     8 *          Gildas Bazin <gbazin@videolan.org> 
    89 * 
    910 * This program is free software; you can redistribute it and/or modify 
     
    3839static int  Open ( vlc_object_t * ); 
    3940static void Close( vlc_object_t * ); 
     41 
     42#define GRANULARITY_TEXT N_("Timeshift granularity") 
     43#define GRANULARITY_LONGTEXT N_( "Size of the temporary files use to store " \ 
     44  "the timeshifted stream." ) 
     45#define DIR_TEXT N_("Timeshift directory") 
     46#define DIR_LONGTEXT N_( "Directory used to store the timeshift temporary " \ 
     47  "files." ) 
    4048 
    4149vlc_module_begin(); 
     
    4755    add_shortcut( "timeshift" ); 
    4856    set_callbacks( Open, Close ); 
     57 
     58    add_integer( "timeshift-granularity", 50, NULL, GRANULARITY_TEXT, 
     59                 GRANULARITY_LONGTEXT, VLC_TRUE ); 
     60    add_directory( "timeshift-dir", 0, 0, DIR_TEXT, DIR_LONGTEXT, VLC_FALSE ); 
    4961vlc_module_end(); 
    5062 
     
    5365 *****************************************************************************/ 
    5466 
     67static int      Seek( access_t *, int64_t ); 
    5568static block_t *Block  ( access_t *p_access ); 
    5669static int      Control( access_t *, int i_query, va_list args ); 
    57 static void     Thread ( access_t * ); 
    58  
    59 #define TIMESHIFT_FIFO_MAX (4*1024*1024) 
     70static void     Thread ( access_t *p_access ); 
     71static int      WriteBlockToFile( access_t *p_access, block_t *p_block ); 
     72static block_t *ReadBlockFromFile( access_t *p_access ); 
     73static char    *GetTmpFilePath( access_t *p_access ); 
     74 
     75#define TIMESHIFT_FIFO_MAX (10*1024*1024) 
    6076#define TIMESHIFT_FIFO_MIN (TIMESHIFT_FIFO_MAX/4) 
     77#define TMP_FILE_MAX 256 
     78 
     79typedef struct ts_entry_t 
     80{ 
     81    FILE *file; 
     82    struct ts_entry_t *p_next; 
     83 
     84} ts_entry_t; 
    6185 
    6286struct access_sys_t 
     
    6488    block_fifo_t *p_fifo; 
    6589 
    66     vlc_bool_t b_opened
    67  
    68     FILE *t1, *t2
    69  
    70     char *psz_tmp1
    71     char *psz_tmp2
    72  
    73     FILE *w
    74     int i_w; 
    75  
    76     FILE *r
     90    int  i_files
     91    int  i_file_size; 
     92    int  i_write_size
     93 
     94    ts_entry_t *p_read_list
     95    ts_entry_t **pp_read_last
     96    ts_entry_t *p_write_list; 
     97    ts_entry_t **pp_write_last
     98 
     99    char *psz_filename_base; 
     100    char *psz_filename
    77101}; 
    78102 
     
    86110    access_sys_t *p_sys; 
    87111    vlc_bool_t b_bool; 
    88 #ifdef WIN32 
    89     char buffer[4096]; 
    90     int i_size; 
    91 #endif 
    92112 
    93113    /* Only work with not pace controled access */ 
     
    107127    p_access->pf_read = NULL; 
    108128    p_access->pf_block = Block; 
    109     p_access->pf_seek = NULL
     129    p_access->pf_seek = Seek
    110130    p_access->pf_control = Control; 
    111  
    112131    p_access->info = p_src->info; 
    113132 
     
    116135    /* */ 
    117136    p_sys->p_fifo = block_FifoNew( p_access ); 
    118     p_sys->b_opened = VLC_FALSE; 
    119     p_sys->t1 = p_sys->t2 = NULL; 
    120     p_sys->w = p_sys->r = NULL; 
    121     p_sys->i_w = 0; 
    122  
    123 #ifdef WIN32 
    124     i_size = GetTempPath( 4095, buffer ); 
    125     if( i_size <= 0 || i_size >= 4095 ) 
    126     { 
    127         if( getcwd( buffer, 4095 ) == NULL ) 
    128             strcpy( buffer, "c:" ); 
    129     } 
    130     /* remove last \\ if any */ 
    131     if( buffer[strlen(buffer)-1] == '\\' ) 
    132         buffer[strlen(buffer)-1] = '\0'; 
    133  
    134     asprintf( &p_sys->psz_tmp1, "%s\\vlc-timeshift-%d-%d-1.dat", 
    135               buffer, GetCurrentProcessId(), p_access->i_object_id ); 
    136     asprintf( &p_sys->psz_tmp2, "%s\\vlc-timeshift-%d-%d-2.dat", 
    137               buffer, GetCurrentProcessId(), p_access->i_object_id ); 
    138 #else 
    139     asprintf( &p_sys->psz_tmp1, "/tmp/vlc-timeshift-%d-%d-1.dat", 
    140               getpid(), p_access->i_object_id ); 
    141     asprintf( &p_sys->psz_tmp2, "/tmp/vlc-timeshift-%d-%d-2.dat", 
    142               getpid(), p_access->i_object_id ); 
    143 #endif 
     137    p_sys->i_write_size = 0; 
     138    p_sys->i_files = 0; 
     139 
     140    p_sys->p_read_list = NULL; 
     141    p_sys->pp_read_last = &p_sys->p_read_list; 
     142    p_sys->p_write_list = NULL; 
     143    p_sys->pp_write_last = &p_sys->p_write_list; 
     144 
     145    var_Create( p_access, "timeshift-dir", 
     146                VLC_VAR_DIRECTORY | VLC_VAR_DOINHERIT ); 
     147    var_Create( p_access, "timeshift-granularity", 
     148                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); 
     149    p_sys->i_file_size = var_GetInteger( p_access, "timeshift-granularity" ); 
     150    if( p_sys->i_file_size < 1 ) p_sys->i_file_size = 1; 
     151    p_sys->i_file_size *= 1024 * 1024; /* In MBytes */ 
     152 
     153    p_sys->psz_filename_base = GetTmpFilePath( p_access ); 
     154    p_sys->psz_filename = malloc( strlen( p_sys->psz_filename_base ) + 1000 ); 
    144155 
    145156    if( vlc_thread_create( p_access, "timeshift thread", Thread, 
     
    160171    access_t     *p_access = (access_t*)p_this; 
    161172    access_sys_t *p_sys = p_access->p_sys; 
    162  
    163     /* */ 
     173    ts_entry_t *p_entry; 
     174    int i; 
     175 
    164176    msg_Dbg( p_access, "timeshift close called" ); 
    165177    vlc_thread_join( p_access ); 
    166178 
    167     if( p_sys->b_opened ) 
    168     { 
    169         if( p_sys->t1 ) fclose( p_sys->t1 ); 
    170         if( p_sys->t2 ) fclose( p_sys->t2 ); 
    171         unlink( p_sys->psz_tmp1 ); 
    172         unlink( p_sys->psz_tmp2 ); 
    173     } 
    174  
    175     free( p_sys->psz_tmp1 ); 
    176     free( p_sys->psz_tmp2 ); 
    177  
     179    for( p_entry = p_sys->p_write_list; p_entry; ) 
     180    { 
     181        ts_entry_t *p_next = p_entry->p_next; 
     182        fclose( p_entry->file ); 
     183        free( p_entry ); 
     184        p_entry = p_next; 
     185    } 
     186    for( p_entry = p_sys->p_read_list; p_entry; ) 
     187    { 
     188        ts_entry_t *p_next = p_entry->p_next; 
     189        fclose( p_entry->file ); 
     190        free( p_entry ); 
     191        p_entry = p_next; 
     192    } 
     193    for( i = 0; i < p_sys->i_files; i++ ) 
     194    { 
     195        sprintf( p_sys->psz_filename, "%s%i.dat", 
     196                 p_sys->psz_filename_base, i ); 
     197        unlink( p_sys->psz_filename ); 
     198    } 
     199 
     200    free( p_sys->psz_filename ); 
     201    free( p_sys->psz_filename_base ); 
    178202    block_FifoRelease( p_sys->p_fifo ); 
    179203    free( p_sys ); 
     
    186210{ 
    187211    access_sys_t *p_sys = p_access->p_sys; 
     212    block_t *p_block; 
    188213 
    189214    if( p_access->b_die ) 
     
    193218    } 
    194219 
    195     return block_FifoGet( p_sys->p_fifo ); 
     220    p_block = block_FifoGet( p_sys->p_fifo ); 
     221    //p_access->info.i_size -= p_block->i_buffer; 
     222    return p_block; 
     223
     224 
     225/***************************************************************************** 
     226 * 
     227 *****************************************************************************/ 
     228static void Thread( access_t *p_access ) 
     229
     230    access_sys_t *p_sys = p_access->p_sys; 
     231    access_t     *p_src = p_access->p_source; 
     232    int i; 
     233 
     234    while( !p_access->b_die ) 
     235    { 
     236        block_t *p_block; 
     237 
     238        /* Get a new block from the source */ 
     239        if( p_src->pf_block ) 
     240        { 
     241            p_block = p_src->pf_block( p_src ); 
     242 
     243            if( p_block == NULL ) 
     244            { 
     245                if( p_src->info.b_eof ) break; 
     246                msleep( 1000 ); 
     247                continue; 
     248            } 
     249        } 
     250        else 
     251        { 
     252            if( ( p_block = block_New( p_access, 2048 ) ) == NULL ) break; 
     253 
     254            p_block->i_buffer = 
     255                p_src->pf_read( p_src, p_block->p_buffer, 2048 ); 
     256 
     257            if( p_block->i_buffer < 0 ) 
     258            { 
     259                block_Release( p_block ); 
     260                if( p_block->i_buffer == 0 ) break; 
     261                msleep( 1000 ); 
     262                continue; 
     263            } 
     264        } 
     265 
     266        /* Write block */ 
     267        if( !p_sys->p_write_list && !p_sys->p_read_list && 
     268            p_sys->p_fifo->i_size < TIMESHIFT_FIFO_MAX ) 
     269        { 
     270            /* If there isn't too much timeshifted data, 
     271             * write directly to FIFO */ 
     272            block_FifoPut( p_sys->p_fifo, p_block ); 
     273 
     274            //p_access->info.i_size += p_block->i_buffer; 
     275            //p_access->info.i_update |= INPUT_UPDATE_SIZE; 
     276 
     277            /* Nothing else to do */ 
     278            continue; 
     279        } 
     280 
     281        WriteBlockToFile( p_access, p_block ); 
     282        block_Release( p_block ); 
     283 
     284        /* Read from file to fill up the fifo */ 
     285        while( p_sys->p_fifo->i_size < TIMESHIFT_FIFO_MIN && 
     286               !p_access->b_die ) 
     287        { 
     288            p_block = ReadBlockFromFile( p_access ); 
     289            if( !p_block ) break; 
     290            block_FifoPut( p_sys->p_fifo, p_block ); 
     291        } 
     292    } 
     293 
     294    msg_Dbg( p_access, "timeshift: EOF" ); 
     295 
     296    /* Send dummy packet to avoid deadlock in TShiftBlock */ 
     297    for( i = 0; i < 2; i++ ) 
     298    { 
     299        block_t *p_dummy = block_New( p_access, 128 ); 
     300        p_dummy->i_flags |= BLOCK_FLAG_DISCONTINUITY; 
     301        memset( p_dummy->p_buffer, 0, p_dummy->i_buffer ); 
     302        block_FifoPut( p_sys->p_fifo, p_dummy ); 
     303    } 
     304
     305 
     306/***************************************************************************** 
     307 * NextFileWrite: 
     308 *****************************************************************************/ 
     309static void NextFileWrite( access_t *p_access ) 
     310
     311    access_sys_t *p_sys = p_access->p_sys; 
     312    ts_entry_t   *p_next; 
     313 
     314    if( !p_sys->p_write_list ) 
     315    { 
     316        p_sys->i_write_size = 0; 
     317        return; 
     318    } 
     319 
     320    p_next = p_sys->p_write_list->p_next; 
     321 
     322    /* Put written file in read list */ 
     323    if( p_sys->i_write_size < p_sys->i_file_size ) 
     324        ftruncate( fileno( p_sys->p_write_list->file ), p_sys->i_write_size ); 
     325 
     326    fseek( p_sys->p_write_list->file, 0, SEEK_SET ); 
     327    *p_sys->pp_read_last = p_sys->p_write_list; 
     328    p_sys->pp_read_last = &p_sys->p_write_list->p_next; 
     329    p_sys->p_write_list->p_next = 0; 
     330 
     331    /* Switch to next file to write */ 
     332    p_sys->p_write_list = p_next; 
     333    if( !p_sys->p_write_list ) p_sys->pp_write_last = &p_sys->p_write_list; 
     334 
     335    p_sys->i_write_size = 0; 
     336
     337 
     338/***************************************************************************** 
     339 * NextFileRead: 
     340 *****************************************************************************/ 
     341static void NextFileRead( access_t *p_access ) 
     342
     343    access_sys_t *p_sys = p_access->p_sys; 
     344    ts_entry_t   *p_next; 
     345 
     346    if( !p_sys->p_read_list ) return; 
     347 
     348    p_next = p_sys->p_read_list->p_next; 
     349 
     350    /* Put read file in write list */ 
     351    fseek( p_sys->p_read_list->file, 0, SEEK_SET ); 
     352    *p_sys->pp_write_last = p_sys->p_read_list; 
     353    p_sys->pp_write_last = &p_sys->p_read_list->p_next; 
     354    p_sys->p_read_list->p_next = 0; 
     355 
     356    /* Switch to next file to read */ 
     357    p_sys->p_read_list = p_next; 
     358    if( !p_sys->p_read_list ) p_sys->pp_read_last = &p_sys->p_read_list; 
     359
     360 
     361/***************************************************************************** 
     362 * WriteBlockToFile: 
     363 *****************************************************************************/ 
     364static int WriteBlockToFile( access_t *p_access, block_t *p_block ) 
     365
     366    access_sys_t *p_sys = p_access->p_sys; 
     367    int i_write, i_buffer; 
     368 
     369    if( p_sys->i_write_size == p_sys->i_file_size ) NextFileWrite( p_access ); 
     370 
     371    /* Open new file if necessary */ 
     372    if( !p_sys->p_write_list ) 
     373    { 
     374        FILE *file; 
     375 
     376        sprintf( p_sys->psz_filename, "%s%i.dat", 
     377                 p_sys->psz_filename_base, p_sys->i_files ); 
     378        file = fopen( p_sys->psz_filename, "w+b" ); 
     379 
     380        if( !file && p_sys->i_files < 2 ) 
     381        { 
     382            /* We just can't work with less than 2 buffer files */ 
     383            msg_Err( p_access, "cannot open temporary file '%s' (%s)", 
     384                     p_sys->psz_filename, strerror(errno) ); 
     385            return VLC_EGENERIC; 
     386        } 
     387        else if( !file ) return VLC_EGENERIC; 
     388 
     389        p_sys->p_write_list = malloc( sizeof(ts_entry_t) ); 
     390        p_sys->p_write_list->p_next = 0; 
     391        p_sys->p_write_list->file = file; 
     392        p_sys->pp_write_last = &p_sys->p_write_list->p_next; 
     393 
     394        p_sys->i_files++; 
     395    } 
     396 
     397    /* Write to file */ 
     398    i_buffer = __MIN( p_block->i_buffer, 
     399                      p_sys->i_file_size - p_sys->i_write_size ); 
     400 
     401    i_write = fwrite( p_block->p_buffer, 1, i_buffer, 
     402                      p_sys->p_write_list->file ); 
     403 
     404    if( i_write > 0 ) p_sys->i_write_size += i_write; 
     405 
     406    //p_access->info.i_size += i_write; 
     407    //p_access->info.i_update |= INPUT_UPDATE_SIZE; 
     408 
     409    if( i_write < i_buffer ) 
     410    { 
     411        /* Looks like we're short of space */ 
     412 
     413        if( !p_sys->p_write_list->p_next ) 
     414        { 
     415            msg_Warn( p_access, "no more space, overwritting old data" ); 
     416            NextFileRead( p_access ); 
     417            NextFileRead( p_access ); 
     418        } 
     419 
     420        /* Make sure we switch to next file in write list */ 
     421        p_sys->i_write_size = p_sys->i_file_size; 
     422    } 
     423 
     424    p_block->p_buffer += i_write; 
     425    p_block->i_buffer -= i_write; 
     426 
     427    /* Check if we have some data left */ 
     428    if( p_block->i_buffer ) return WriteBlockToFile( p_access, p_block ); 
     429 
     430    return VLC_SUCCESS; 
     431
     432 
     433/***************************************************************************** 
     434 * ReadBlockFromFile: 
     435 *****************************************************************************/ 
     436static block_t *ReadBlockFromFile( access_t *p_access ) 
     437
     438    access_sys_t *p_sys = p_access->p_sys; 
     439    block_t *p_block; 
     440 
     441    if( !p_sys->p_read_list && p_sys->p_write_list ) 
     442    { 
     443        /* Force switching to next write file, that should 
     444         * give us something to read */ 
     445        NextFileWrite( p_access ); 
     446    } 
     447 
     448    if( !p_sys->p_read_list ) return 0; 
     449 
     450    p_block = block_New( p_access, 4096 ); 
     451    p_block->i_buffer = fread( p_block->p_buffer, 1, 4096, 
     452                               p_sys->p_read_list->file ); 
     453 
     454    if( p_block->i_buffer == 0 ) NextFileRead( p_access ); 
     455 
     456    //p_access->info.i_size -= p_block->i_buffer; 
     457    //p_access->info.i_update |= INPUT_UPDATE_SIZE; 
     458 
     459    return p_block; 
     460
     461 
     462/***************************************************************************** 
     463 * Seek: seek to a specific location in a file 
     464 *****************************************************************************/ 
     465static int Seek( access_t *p_access, int64_t i_pos ) 
     466
     467    //access_sys_t *p_sys = p_access->p_sys; 
     468    return VLC_SUCCESS; 
    196469} 
    197470 
     
    209482    switch( i_query ) 
    210483    { 
    211         /* */ 
    212484        case ACCESS_CAN_SEEK: 
    213485        case ACCESS_CAN_FASTSEEK: 
    214486            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); 
    215             *pb_bool = VLC_FALSE; 
     487            *pb_bool = VLC_TRUE; 
    216488            break; 
    217489 
     
    222494            break; 
    223495 
    224         /* */ 
    225496        case ACCESS_GET_MTU: 
    226497            pi_int = (int*)va_arg( args, int * ); 
     
    231502            pi_64 = (int64_t*)va_arg( args, int64_t * ); 
    232503            return access2_Control( p_src, ACCESS_GET_PTS_DELAY, pi_64 ); 
    233         /* */ 
     504 
    234505        case ACCESS_SET_PAUSE_STATE: 
    235506            return VLC_SUCCESS; 
     
    255526 
    256527/***************************************************************************** 
    257  * 
    258  *****************************************************************************/ 
    259 static void Thread( access_t *p_access ) 
    260 
    261     access_sys_t *p_sys = p_access->p_sys; 
    262     access_t     *p_src = p_access->p_source; 
    263     int i_loop = 0; 
    264  
    265     while( !p_access->b_die ) 
    266     { 
    267         block_t *p_block; 
    268  
    269         /* Get a new block */ 
    270         if( p_src->pf_block ) 
    271         { 
    272             p_block = p_src->pf_block( p_src ); 
    273  
    274             if( p_block == NULL ) 
    275             { 
    276                 if( p_src->info.b_eof ) 
    277                     break; 
    278  
    279                 msleep( 1000 ); 
    280                 continue; 
    281             } 
    282         } 
    283         else 
    284         { 
    285             if( ( p_block = block_New( p_access, 2048 ) ) == NULL ) 
    286                 break; 
    287  
    288             p_block->i_buffer = p_src->pf_read( p_src, p_block->p_buffer, 2048); 
    289             if( p_block->i_buffer < 0 ) 
    290             { 
    291                 block_Release( p_block ); 
    292                 if( p_block->i_buffer == 0 ) 
    293                     break; 
    294                 msleep( 1000 ); 
    295                 continue; 
    296             } 
    297         } 
    298  
    299         /* Open dump files if we need them */ 
    300         if( p_sys->p_fifo->i_size >= TIMESHIFT_FIFO_MAX && !p_sys->b_opened ) 
    301         { 
    302             msg_Dbg( p_access, "opening first temporary files (%s)", 
    303                      p_sys->psz_tmp1 ); 
    304  
    305             p_sys->b_opened = VLC_TRUE; 
    306             p_sys->t1 = p_sys->t2 = NULL; 
    307             p_sys->w = p_sys->r = NULL; 
    308  
    309             p_sys->t1 = fopen( p_sys->psz_tmp1, "w+b" ); 
    310             if( p_sys->t1 ) 
    311             { 
    312                 msg_Dbg( p_access, "opening second temporary files (%s)", 
    313                          p_sys->psz_tmp2 ); 
    314  
    315                 p_sys->t2 = fopen( p_sys->psz_tmp2, "w+b" ); 
    316                 if( p_sys->t2 ) 
    317                 { 
    318                     p_sys->w = p_sys->t1; 
    319                     p_sys->i_w = 0; 
    320  
    321                     msg_Dbg( p_access, "start writing into temporary file" ); 
    322                 } 
    323                 else 
    324                 { 
    325                     msg_Err( p_access, "cannot open temporary file '%s' (%s)", 
    326                              p_sys->psz_tmp2, strerror(errno) ); 
    327                     fclose( p_sys->t1 ); 
    328                     p_sys->t1 = NULL; 
    329                 } 
    330             } 
    331             else 
    332             { 
    333                 msg_Err( p_access, "cannot open temporary file '%s' (%s)", 
    334                          p_sys->psz_tmp1, strerror(errno) ); 
    335             } 
    336         } 
    337  
    338         if( p_sys->w ) 
    339         { 
    340             int i_write; 
    341  
    342             /* Dump the block */ 
    343             i_write = fwrite( p_block->p_buffer, 1, p_block->i_buffer, 
    344                               p_sys->w ); 
    345             block_Release( p_block ); 
    346  
    347             if( i_write > 0 ) 
    348                 p_sys->i_w += i_write; 
    349             else 
    350                 msg_Warn( p_access, "cannot write data" ); 
    351  
    352             /* Start reading from a file if fifo isn't at 25% */ 
    353             if( p_sys->p_fifo->i_size < TIMESHIFT_FIFO_MIN && !p_sys->r ) 
    354             { 
    355                 msg_Dbg( p_access, "start reading from temporary file (dumped=%d)", p_sys->i_w ); 
    356  
    357                 p_sys->r = p_sys->w; 
    358                 fseek( p_sys->r, 0, SEEK_SET ); 
    359  
    360                 p_sys->w = p_sys->t2; 
    361                 p_sys->i_w = 0; 
    362             } 
    363  
    364             if( p_sys->r ) 
    365             { 
    366                 while( p_sys->p_fifo->i_size < TIMESHIFT_FIFO_MIN ) 
    367                 { 
    368                     p_block = block_New( p_access, 4096 ); 
    369                     p_block->i_buffer = fread( p_block->p_buffer, 1, 4096, 
    370                                                p_sys->r ); 
    371  
    372                     if( p_block->i_buffer > 0 ) 
    373                     { 
    374                         block_FifoPut( p_sys->p_fifo, p_block ); 
    375                     } 
    376                     else if( p_sys->i_w > 32*1024) 
    377                     { 
    378                         FILE *tmp; 
    379                         block_Release( p_block ); 
    380  
    381                         msg_Dbg( p_access, "switching temporary files (dumped=%d)", p_sys->i_w ); 
    382  
    383                         /* Switch read/write */ 
    384                         tmp = p_sys->r; 
    385  
    386                         p_sys->r = p_sys->w; 
    387                         fseek( p_sys->r, 0, SEEK_SET ); 
    388  
    389                         p_sys->w = tmp; 
    390                         fseek( p_sys->w, 0, SEEK_SET ); 
    391                         ftruncate( fileno(p_sys->w), 0 ); 
    392                         p_sys->i_w = 0; 
    393                     } 
    394                     else 
    395                     { 
    396                         msg_Dbg( p_access, "removing temporary files" ); 
    397  
    398                         /* We will remove the need of tmp files */ 
    399                         if( p_sys->i_w > 0 ) 
    400                         { 
    401                             msg_Dbg( p_access, "loading temporary file" ); 
    402                             fseek( p_sys->w, 0, SEEK_SET ); 
    403                             for( ;; ) 
    404                             { 
    405                                 p_block = block_New( p_access, 4096 ); 
    406                                 p_block->i_buffer = fread( p_block->p_buffer, 
    407                                                            1, 4096, 
    408                                                            p_sys->w ); 
    409                                 if( p_block->i_buffer <= 0 ) 
    410                                 { 
    411                                     block_Release( p_block ); 
    412                                     break; 
    413                                 } 
    414                                 block_FifoPut( p_sys->p_fifo, p_block ); 
    415                             } 
    416                         } 
    417  
    418                         p_sys->b_opened = VLC_FALSE; 
    419  
    420                         fclose( p_sys->t1 ); 
    421                         fclose( p_sys->t2 ); 
    422  
    423                         p_sys->t1 = p_sys->t2 = NULL; 
    424                         p_sys->w = p_sys->r = NULL; 
    425  
    426                         unlink( p_sys->psz_tmp1 ); 
    427                         unlink( p_sys->psz_tmp2 ); 
    428                         break; 
    429                     } 
    430                 } 
    431             } 
    432         } 
    433         else if( p_sys->p_fifo->i_size < TIMESHIFT_FIFO_MAX ) 
    434         { 
    435             block_FifoPut( p_sys->p_fifo, p_block ); 
    436         } 
    437         else 
    438         { 
    439             /* We failed to opened files so trash new data */ 
    440             block_Release( p_block ); 
    441         } 
    442 #if 0 
    443         if( (i_loop % 400) == 0 ) 
    444             msg_Dbg( p_access, "timeshift: buff=%d", p_sys->p_fifo->i_size ); 
     528 * GetTmpFilePath: 
     529 *****************************************************************************/ 
     530#ifdef WIN32 
     531#define getpid() GetCurrentProcessId() 
    445532#endif 
    446         i_loop++; 
    447     } 
    448  
    449     msg_Warn( p_access, "timeshift: EOF" ); 
    450  
    451     /* Send dummy packet to avoid deadlock in TShiftBlock */ 
    452     for( i_loop = 0; i_loop < 2; i_loop++ ) 
    453     { 
    454         block_t *p_dummy = block_New( p_access, 128 ); 
    455  
    456         p_dummy->i_flags |= BLOCK_FLAG_DISCONTINUITY; 
    457         memset( p_dummy->p_buffer, 0, p_dummy->i_buffer ); 
    458  
    459         block_FifoPut( p_sys->p_fifo, p_dummy ); 
    460     } 
    461 
    462  
     533static char *GetTmpFilePath( access_t *p_access ) 
     534
     535    char *psz_dir = var_GetString( p_access, "timeshift-dir" ); 
     536    char *psz_filename_base; 
     537 
     538    if( psz_dir && !*psz_dir ) 
     539    { 
     540        free( psz_dir ); 
     541        psz_dir = 0; 
     542    } 
     543 
     544    if( !psz_dir ) 
     545    { 
     546#ifdef WIN32 
     547        int i_size; 
     548 
     549        psz_dir = malloc( MAX_PATH + 1 ); 
     550        i_size = GetTempPath( MAX_PATH, psz_dir ); 
     551        if( i_size <= 0 || i_size > MAX_PATH ) 
     552        { 
     553            if( !getcwd( psz_dir, MAX_PATH ) ) strcpy( psz_dir, "c:" ); 
     554        } 
     555 
     556        /* remove last \\ if any */ 
     557        if( psz_dir[strlen(psz_dir)-1] == '\\' ) 
     558            psz_dir[strlen(psz_dir)-1] = '\0'; 
     559#else 
     560 
     561        psz_dir = strdup( "/tmp" ); 
     562#endif 
     563    } 
     564 
     565    asprintf( &psz_filename_base, "%s/vlc-timeshift-%d-%d-", 
     566              psz_dir, getpid(), p_access->i_object_id ); 
     567 
     568    return psz_filename_base; 
     569