Changeset 6112 for pjproject


Ignore:
Timestamp:
Nov 29, 2019 4:21:17 AM (4 years ago)
Author:
ming
Message:

Fixed #2251: Deadlock between PJSUA LOCK and conference mutex

Location:
pjproject/trunk
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/avi_stream.h

    r3715 r6112  
    139139 
    140140 
     141#if !DEPRECATED_FOR_TICKET_2251 
    141142/** 
    142143 * Register a callback to be called when the file reading has reached the 
     
    159160                              pj_status_t (*cb)(pjmedia_avi_stream *stream, 
    160161                                                void *usr_data)); 
     162#endif 
     163 
     164 
     165/** 
     166 * Register a callback to be called when the file reading has reached the 
     167 * end of file. If the file is set to play repeatedly, then the callback 
     168 * will be called multiple times. Note that only one callback can be  
     169 * registered for each AVI stream. 
     170 * 
     171 * @param stream        The AVI stream. 
     172 * @param user_data     User data to be specified in the callback 
     173 * @param cb            Callback to be called. Note that if 
     174 *                      application wishes to stop the playback, it 
     175 *                      can disconnect the port in the callback, and 
     176 *                      only after all connections have been removed 
     177 *                      could the application safely destroy the port. 
     178 * 
     179 * @return              PJ_SUCCESS on success. 
     180 */ 
     181PJ_DECL(pj_status_t)  
     182pjmedia_avi_stream_set_eof_cb2(pjmedia_avi_stream *stream, 
     183                               void *user_data, 
     184                               void (*cb)(pjmedia_avi_stream *stream, 
     185                                          void *usr_data)); 
     186 
    161187 
    162188/** 
  • pjproject/trunk/pjmedia/include/pjmedia/event.h

    r6106 r6112  
    106106     * Transport media error. 
    107107     */ 
    108     PJMEDIA_EVENT_MEDIA_TP_ERR = PJMEDIA_FOURCC('T', 'E', 'R', 'R') 
     108    PJMEDIA_EVENT_MEDIA_TP_ERR = PJMEDIA_FOURCC('T', 'E', 'R', 'R'), 
     109 
     110    /** 
     111     * Callback event. Currently for internal use only. 
     112     */ 
     113    PJMEDIA_EVENT_CALLBACK = PJMEDIA_FOURCC('C', 'B', ' ', ' ') 
    109114 
    110115} pjmedia_event_type; 
  • pjproject/trunk/pjmedia/include/pjmedia/mem_port.h

    r3553 r6112  
    8787 
    8888 
     89#if !DEPRECATED_FOR_TICKET_2251 
    8990/** 
    9091 * Register a callback to be called when the buffer reading has reached the 
     
    107108                               pj_status_t (*cb)(pjmedia_port *port, 
    108109                                                 void *usr_data)); 
    109  
     110#endif 
     111 
     112 
     113/** 
     114 * Register a callback to be called when the buffer reading has reached the 
     115 * end of buffer. If the player is set to play repeatedly, then the callback 
     116 * will be called multiple times. Note that only one callback can be  
     117 * registered for each player port. 
     118 * 
     119 * @param port          The memory player port. 
     120 * @param user_data     User data to be specified in the callback 
     121 * @param cb            Callback to be called. Note that if 
     122 *                      application wishes to stop the playback, it 
     123 *                      can disconnect the port in the callback, and 
     124 *                      only after all connections have been removed 
     125 *                      could the application safely destroy the port. 
     126 * 
     127 * @return              PJ_SUCCESS on success. 
     128 */ 
     129PJ_DECL(pj_status_t)  
     130pjmedia_mem_player_set_eof_cb2(pjmedia_port *port, 
     131                               void *user_data, 
     132                               void (*cb)(pjmedia_port *port, 
     133                                          void *usr_data)); 
    110134 
    111135/** 
     
    152176 
    153177 
     178#if !DEPRECATED_FOR_TICKET_2251 
    154179/** 
    155180 * Register a callback to be called when no space left in the buffer. 
     
    175200                               pj_status_t (*cb)(pjmedia_port *port, 
    176201                                                 void *usr_data)); 
     202#endif 
     203 
     204 
     205/** 
     206 * Register a callback to be called when no space left in the buffer. 
     207 * 
     208 * @param port          The memory recorder port. 
     209 * @param user_data     User data to be specified in the callback 
     210 * @param cb            Callback to be called. Note that if 
     211 *                      application wishes to stop the recording, it 
     212 *                      can disconnect the port in the callback, and 
     213 *                      only after all connections have been removed 
     214 *                      could the application safely destroy the port. 
     215 * 
     216 * @return              PJ_SUCCESS on success. 
     217 */ 
     218PJ_DECL(pj_status_t) 
     219pjmedia_mem_capture_set_eof_cb2(pjmedia_port *port, 
     220                                void *user_data, 
     221                                void (*cb)(pjmedia_port *port, 
     222                                           void *usr_data)); 
     223 
    177224 
    178225/** 
  • pjproject/trunk/pjmedia/include/pjmedia/port.h

    r3893 r6112  
    188188 
    189189 
     190/* Since media port's callback is called synchronously and has a return value, 
     191 * it can introduce a deadlock when a mutex is held before calling it. 
     192 * To prevent this, media ports' set_eof_cb() and set_cb() functions have 
     193 * been deprecated and replaced by set_eof_cb2() and set_cb2(), which 
     194 * will call the callback asynchronously without expecting any return value. 
     195 * 
     196 * See also https://trac.pjsip.org/repos/ticket/2251. 
     197 */ 
     198#ifndef DEPRECATED_FOR_TICKET_2251 
     199#  define DEPRECATED_FOR_TICKET_2251    0 
     200#endif 
     201 
     202 
    190203/** 
    191204 * Create 32bit port signature from ASCII characters. 
  • pjproject/trunk/pjmedia/include/pjmedia/wav_playlist.h

    r3553 r6112  
    7373 
    7474 
     75#if !DEPRECATED_FOR_TICKET_2251 
    7576/** 
    7677 * Register a callback to be called when the file reading has reached the 
     
    9394                                pj_status_t (*cb)(pjmedia_port *port, 
    9495                                                  void *usr_data)); 
     96#endif 
     97 
     98 
     99/** 
     100 * Register a callback to be called when the file reading has reached the 
     101 * end of file of the last file. If the file is set to play repeatedly,  
     102 * then the callback will be called multiple times. Note that only one  
     103 * callback can be registered for each file port. 
     104 * 
     105 * @param port          The WAV play list port. 
     106 * @param user_data     User data to be specified in the callback 
     107 * @param cb            Callback to be called. Note that if 
     108 *                      application wishes to stop the playback, it 
     109 *                      can disconnect the port in the callback, and 
     110 *                      only after all connections have been removed 
     111 *                      could the application safely destroy the port. 
     112 * 
     113 * @return              PJ_SUCCESS on success. 
     114 */ 
     115PJ_DECL(pj_status_t) 
     116pjmedia_wav_playlist_set_eof_cb2(pjmedia_port *port, 
     117                                 void *user_data, 
     118                                 void (*cb)(pjmedia_port *port, 
     119                                            void *usr_data)); 
    95120 
    96121 
  • pjproject/trunk/pjmedia/include/pjmedia/wav_port.h

    r4793 r6112  
    152152 
    153153 
     154#if !DEPRECATED_FOR_TICKET_2251 
    154155/** 
    155156 * Register a callback to be called when the file reading has reached the 
     
    167168 * @return              PJ_SUCCESS on success. 
    168169 */ 
    169 PJ_DECL(pj_status_t)  
     170PJ_DECL(pj_status_t) 
    170171pjmedia_wav_player_set_eof_cb( pjmedia_port *port, 
    171172                               void *user_data, 
    172173                               pj_status_t (*cb)(pjmedia_port *port, 
    173174                                                 void *usr_data)); 
     175#endif 
     176 
     177 
     178/** 
     179 * Register a callback to be called when the file reading has reached the 
     180 * end of file. If the file is set to play repeatedly, then the callback 
     181 * will be called multiple times. Note that only one callback can be  
     182 * registered for each file port. 
     183 * 
     184 * @param port          The file player port. 
     185 * @param user_data     User data to be specified in the callback 
     186 * @param cb            Callback to be called. Note that if 
     187 *                      application wishes to stop the playback, it 
     188 *                      can disconnect the port in the callback, and 
     189 *                      only after all connections have been removed 
     190 *                      could the application safely destroy the port. 
     191 * 
     192 * @return              PJ_SUCCESS on success. 
     193 */ 
     194PJ_DECL(pj_status_t) 
     195pjmedia_wav_player_set_eof_cb2(pjmedia_port *port, 
     196                               void *user_data, 
     197                               void (*cb)(pjmedia_port *port, 
     198                                          void *usr_data)); 
     199 
    174200 
    175201/** 
     
    256282 
    257283 
     284#if !DEPRECATED_FOR_TICKET_2251 
    258285/** 
    259286 * Register the callback to be called when the file writing has reached 
     
    278305                                pj_status_t (*cb)(pjmedia_port *port, 
    279306                                                  void *usr_data)); 
     307#endif 
     308 
     309 
     310/** 
     311 * Register the callback to be called when the file writing has reached 
     312 * certain size. Application can use this callback, for example, to limit 
     313 * the size of the output file. 
     314 * 
     315 * @param port          The file writer port. 
     316 * @param pos           The file position on which the callback will be called. 
     317 * @param user_data     User data to be specified in the callback, and will be 
     318 *                      given on the callback. 
     319 * @param cb            Callback to be called. Note that if 
     320 *                      application wishes to stop the writing, it 
     321 *                      can disconnect the port in the callback, and 
     322 *                      only after all connections have been removed 
     323 *                      could the application safely destroy the port. 
     324 * 
     325 * @return              PJ_SUCCESS on success. 
     326 */ 
     327PJ_DECL(pj_status_t)  
     328pjmedia_wav_writer_port_set_cb2(pjmedia_port *port, 
     329                                pj_size_t pos, 
     330                                void *user_data, 
     331                                void (*cb)(pjmedia_port *port, 
     332                                           void *usr_data)); 
    280333 
    281334 
  • pjproject/trunk/pjmedia/src/pjmedia/avi_player.c

    r5659 r6112  
    139139 
    140140    pj_status_t    (*cb)(pjmedia_port*, void*); 
     141    pj_bool_t        subscribed; 
     142    void           (*cb2)(pjmedia_port*, void*); 
    141143}; 
    142144 
     
    579581 
    580582 
     583#if !DEPRECATED_FOR_TICKET_2251 
    581584/* 
    582585 * Register a callback to be called when the file reading has reached the 
     
    597600    PJ_ASSERT_RETURN(stream->info.signature == SIGNATURE, -PJ_EINVALIDOP); 
    598601 
     602    PJ_LOG(1, (THIS_FILE, "pjmedia_avi_stream_set_eof_cb() is deprecated. " 
     603               "Use pjmedia_avi_stream_set_eof_cb2() instead.")); 
     604 
    599605    fport = (struct avi_reader_port*) stream; 
    600606 
     
    602608    fport->cb = cb; 
    603609 
     610    return PJ_SUCCESS; 
     611} 
     612#endif 
     613 
     614 
     615/* 
     616 * Register a callback to be called when the file reading has reached the 
     617 * end of file. 
     618 */ 
     619PJ_DEF(pj_status_t) 
     620pjmedia_avi_stream_set_eof_cb2(pjmedia_avi_stream *stream, 
     621                               void *user_data, 
     622                               void (*cb)(pjmedia_avi_stream *stream, 
     623                                          void *usr_data)) 
     624{ 
     625    struct avi_reader_port *fport; 
     626 
     627    /* Sanity check */ 
     628    PJ_ASSERT_RETURN(stream, -PJ_EINVAL); 
     629 
     630    /* Check that this is really a player port */ 
     631    PJ_ASSERT_RETURN(stream->info.signature == SIGNATURE, -PJ_EINVALIDOP); 
     632 
     633    fport = (struct avi_reader_port*) stream; 
     634 
     635    fport->base.port_data.pdata = user_data; 
     636    fport->cb2 = cb; 
     637 
     638    return PJ_SUCCESS; 
     639} 
     640 
     641 
     642static pj_status_t file_on_event(pjmedia_event *event, 
     643                                 void *user_data) 
     644{ 
     645    struct avi_reader_port *fport = (struct avi_reader_port*)user_data; 
     646 
     647    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     648        if (fport->cb2) 
     649            (*fport->cb2)(&fport->base, fport->base.port_data.pdata); 
     650    } 
     651     
    604652    return PJ_SUCCESS; 
    605653} 
     
    625673 
    626674        /* Call callback, if any */ 
    627         if (fport->cb) 
     675        if (fport->cb2) { 
     676            pj_bool_t no_loop = (fport->options & PJMEDIA_AVI_FILE_NO_LOOP); 
     677 
     678            if (!fport->subscribed) { 
     679                status = pjmedia_event_subscribe(NULL, &file_on_event, 
     680                                                 fport, fport); 
     681                fport->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     682                                    PJ_FALSE; 
     683            } 
     684 
     685            if (fport->subscribed && fport->eof != 2) { 
     686                pjmedia_event event; 
     687 
     688                if (no_loop) { 
     689                    /* To prevent the callback from being called repeatedly */ 
     690                    fport->eof = 2; 
     691                } else { 
     692                    fport->eof = PJ_FALSE; 
     693                    pj_file_setpos(fport->fd, fport->start_data, PJ_SEEK_SET); 
     694                } 
     695 
     696                pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     697                                   NULL, fport); 
     698                pjmedia_event_publish(NULL, fport, &event, 
     699                                      PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     700            } 
     701             
     702            /* Should not access player port after this since 
     703             * it might have been destroyed by the callback. 
     704             */ 
     705            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     706            frame->size = 0; 
     707             
     708            return (no_loop? PJ_EEOF: PJ_SUCCESS); 
     709 
     710        } else if (fport->cb) { 
    628711            status = (*fport->cb)(this_port, fport->base.port_data.pdata); 
     712        } 
    629713 
    630714        /* If callback returns non PJ_SUCCESS or 'no loop' is specified, 
     
    785869    pj_assert(this_port->info.signature == SIGNATURE); 
    786870 
     871    if (fport->subscribed) { 
     872        pjmedia_event_unsubscribe(NULL, &file_on_event, fport, fport); 
     873        fport->subscribed = PJ_FALSE; 
     874    } 
     875 
    787876    if (fport->fd != (pj_oshandle_t) (pj_ssize_t)-1) 
    788877        pj_file_close(fport->fd); 
  • pjproject/trunk/pjmedia/src/pjmedia/mem_capture.c

    r3664 r6112  
    2121#include <pj/assert.h> 
    2222#include <pj/errno.h> 
     23#include <pj/log.h> 
    2324#include <pj/pool.h> 
    2425 
     
    4344    pj_status_t    (*cb)(pjmedia_port *port, 
    4445                         void *user_data); 
     46    pj_bool_t        subscribed; 
     47    void           (*cb2)(pjmedia_port*, void*); 
    4548}; 
    4649 
     
    102105 
    103106 
     107#if !DEPRECATED_FOR_TICKET_2251 
    104108/* 
    105109 * Register a callback to be called when the file reading has reached the 
     
    116120                     PJ_EINVALIDOP); 
    117121 
     122    PJ_LOG(1, (THIS_FILE, "pjmedia_mem_capture_set_eof_cb() is deprecated. " 
     123               "Use pjmedia_mem_capture_set_eof_cb2() instead.")); 
     124 
    118125    rec = (struct mem_rec*) port; 
    119126    rec->user_data = user_data; 
     
    121128 
    122129    return PJ_SUCCESS; 
     130} 
     131#endif 
     132 
     133 
     134/* 
     135 * Register a callback to be called when the file reading has reached the 
     136 * end of buffer. 
     137 */ 
     138PJ_DEF(pj_status_t) pjmedia_mem_capture_set_eof_cb2( pjmedia_port *port, 
     139                                void *user_data, 
     140                                void (*cb)(pjmedia_port *port, 
     141                                           void *usr_data)) 
     142{ 
     143    struct mem_rec *rec; 
     144 
     145    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, 
     146                     PJ_EINVALIDOP); 
     147 
     148    rec = (struct mem_rec*) port; 
     149    rec->user_data = user_data; 
     150    rec->cb2 = cb; 
     151 
     152    return PJ_SUCCESS; 
    123153}  
    124154 
     
    137167    } 
    138168    return rec->write_pos - rec->buffer; 
     169} 
     170 
     171 
     172static pj_status_t rec_on_event(pjmedia_event *event, 
     173                                void *user_data) 
     174{ 
     175    struct mem_rec *rec = (struct mem_rec *)user_data; 
     176 
     177    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     178        if (rec->cb2) 
     179            (*rec->cb2)(&rec->base, rec->base.port_data.pdata); 
     180    } 
     181     
     182    return PJ_SUCCESS; 
    139183} 
    140184 
     
    178222             
    179223            /* Call callback, if any */ 
    180             if (rec->cb) { 
     224            if (rec->cb2) { 
     225                if (!rec->subscribed) { 
     226                    pj_status_t status; 
     227 
     228                    status = pjmedia_event_subscribe(NULL, rec_on_event, 
     229                                                 rec, rec); 
     230                    rec->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     231                                        PJ_FALSE; 
     232                } 
     233 
     234                if (rec->subscribed) { 
     235                    pjmedia_event event; 
     236 
     237                    pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     238                                       NULL, rec); 
     239                    pjmedia_event_publish(NULL, rec, &event, 
     240                                          PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     241                } 
     242 
     243                return PJ_SUCCESS; 
     244 
     245            } else if (rec->cb) { 
    181246                pj_status_t status; 
    182247                 
     
    225290    rec = (struct mem_rec*) this_port; 
    226291 
     292    if (rec->subscribed) { 
     293        pjmedia_event_unsubscribe(NULL, &rec_on_event, rec, rec); 
     294        rec->subscribed = PJ_FALSE; 
     295    } 
     296 
    227297    if(rec->cb && PJ_FALSE == rec->eof) { 
    228298        rec->eof = PJ_TRUE; 
  • pjproject/trunk/pjmedia/src/pjmedia/mem_player.c

    r3664 r6112  
    2121#include <pj/assert.h> 
    2222#include <pj/errno.h> 
     23#include <pj/log.h> 
    2324#include <pj/pool.h> 
    2425 
     
    4445    pj_status_t    (*cb)(pjmedia_port *port, 
    4546                         void *user_data); 
    46  
     47    pj_bool_t        subscribed; 
     48    void           (*cb2)(pjmedia_port*, void*); 
    4749}; 
    4850 
     
    102104 
    103105 
    104  
     106#if !DEPRECATED_FOR_TICKET_2251 
    105107/* 
    106108 * Register a callback to be called when the file reading has reached the 
     
    117119                     PJ_EINVALIDOP); 
    118120 
     121    PJ_LOG(1, (THIS_FILE, "pjmedia_mem_player_set_eof_cb() is deprecated. " 
     122               "Use pjmedia_mem_player_set_eof_cb2() instead.")); 
     123 
    119124    player = (struct mem_player*) port; 
    120125    player->user_data = user_data; 
     
    123128    return PJ_SUCCESS; 
    124129} 
     130#endif 
     131 
     132 
     133/* 
     134 * Register a callback to be called when the file reading has reached the 
     135 * end of buffer. 
     136 */ 
     137PJ_DEF(pj_status_t) pjmedia_mem_player_set_eof_cb2( pjmedia_port *port, 
     138                               void *user_data, 
     139                               void (*cb)(pjmedia_port *port, 
     140                                          void *usr_data)) 
     141{ 
     142    struct mem_player *player; 
     143 
     144    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, 
     145                     PJ_EINVALIDOP); 
     146 
     147    player = (struct mem_player*) port; 
     148    player->user_data = user_data; 
     149    player->cb2 = cb; 
     150 
     151    return PJ_SUCCESS; 
     152} 
    125153 
    126154 
     
    131159    PJ_UNUSED_ARG(frame); 
    132160 
     161    return PJ_SUCCESS; 
     162} 
     163 
     164 
     165static pj_status_t player_on_event(pjmedia_event *event, 
     166                                   void *user_data) 
     167{ 
     168    struct mem_player *player = (struct mem_player *)user_data; 
     169 
     170    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     171        if (player->cb2) 
     172            (*player->cb2)(&player->base, player->base.port_data.pdata); 
     173    } 
     174     
    133175    return PJ_SUCCESS; 
    134176} 
     
    151193 
    152194        /* Call callback, if any */ 
    153         if (player->cb) 
     195        if (player->cb2) { 
     196            pj_bool_t no_loop = (player->options & PJMEDIA_MEM_NO_LOOP); 
     197 
     198            if (!player->subscribed) { 
     199                status = pjmedia_event_subscribe(NULL, &player_on_event, 
     200                                                 player, player); 
     201                player->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     202                                    PJ_FALSE; 
     203            } 
     204 
     205            if (player->subscribed && player->eof != 2) { 
     206                pjmedia_event event; 
     207 
     208                if (no_loop) { 
     209                    /* To prevent the callback from being called repeatedly */ 
     210                    player->eof = 2; 
     211                } else { 
     212                    player->eof = PJ_FALSE; 
     213                } 
     214 
     215                pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     216                                   NULL, player); 
     217                pjmedia_event_publish(NULL, player, &event, 
     218                                      PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     219            } 
     220 
     221            /* Should not access player port after this since 
     222             * it might have been destroyed by the callback. 
     223             */ 
     224            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     225            frame->size = 0; 
     226             
     227            return (no_loop? PJ_EEOF: PJ_SUCCESS); 
     228 
     229        } else if (player->cb) { 
    154230            status = (*player->cb)(this_port, player->user_data); 
     231        } 
    155232 
    156233        /* If callback returns non PJ_SUCCESS or 'no loop' is specified 
     
    158235         * it might have been destroyed by the callback). 
    159236         */ 
    160         if ((status != PJ_SUCCESS) || (player->options & PJMEDIA_MEM_NO_LOOP)) { 
     237        if ((status != PJ_SUCCESS) || (player->options & PJMEDIA_MEM_NO_LOOP)) 
     238        { 
    161239            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     240            frame->size = 0; 
    162241            return PJ_EEOF; 
    163242        } 
     
    213292static pj_status_t mem_on_destroy(pjmedia_port *this_port) 
    214293{ 
     294    struct mem_player *player; 
     295 
    215296    PJ_ASSERT_RETURN(this_port->info.signature == SIGNATURE, 
    216                      PJ_EINVALIDOP); 
     297                     PJ_EINVALIDOP); 
     298 
     299    player = (struct mem_player*) this_port; 
     300 
     301    if (player->subscribed) { 
     302        pjmedia_event_unsubscribe(NULL, &player_on_event, player, player); 
     303        player->subscribed = PJ_FALSE; 
     304    } 
    217305 
    218306    /* Destroy signature */ 
  • pjproject/trunk/pjmedia/src/pjmedia/wav_player.c

    r6061 r6112  
    7474 
    7575    pj_status_t    (*cb)(pjmedia_port*, void*); 
     76    pj_bool_t        subscribed; 
     77    void           (*cb2)(pjmedia_port*, void*); 
    7678}; 
    7779 
     
    548550 
    549551 
    550  
     552#if !DEPRECATED_FOR_TICKET_2251 
    551553/* 
    552554 * Register a callback to be called when the file reading has reached the 
     
    566568    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, -PJ_EINVALIDOP); 
    567569 
     570    PJ_LOG(1, (THIS_FILE, "pjmedia_wav_player_set_eof_cb() is deprecated. " 
     571               "Use pjmedia_wav_player_set_eof_cb2() instead.")); 
     572 
    568573    fport = (struct file_reader_port*) port; 
    569574 
     
    571576    fport->cb = cb; 
    572577 
     578    return PJ_SUCCESS; 
     579} 
     580#endif 
     581 
     582 
     583/* 
     584 * Register a callback to be called when the file reading has reached the 
     585 * end of file. 
     586 */ 
     587PJ_DEF(pj_status_t) pjmedia_wav_player_set_eof_cb2(pjmedia_port *port, 
     588                               void *user_data, 
     589                               void (*cb)(pjmedia_port *port, 
     590                                          void *usr_data)) 
     591{ 
     592    struct file_reader_port *fport; 
     593 
     594    /* Sanity check */ 
     595    PJ_ASSERT_RETURN(port, -PJ_EINVAL); 
     596 
     597    /* Check that this is really a player port */ 
     598    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, -PJ_EINVALIDOP); 
     599 
     600    fport = (struct file_reader_port*) port; 
     601 
     602    fport->base.port_data.pdata = user_data; 
     603    fport->cb2 = cb; 
     604 
     605    return PJ_SUCCESS; 
     606} 
     607 
     608 
     609static pj_status_t file_on_event(pjmedia_event *event, 
     610                                 void *user_data) 
     611{ 
     612    struct file_reader_port *fport = (struct file_reader_port*)user_data; 
     613 
     614    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     615        if (fport->cb2) 
     616            (*fport->cb2)(&fport->base, fport->base.port_data.pdata); 
     617    } 
     618     
    573619    return PJ_SUCCESS; 
    574620} 
     
    595641 
    596642        /* Call callback, if any */ 
    597         if (fport->cb) 
     643        if (fport->cb2) { 
     644            pj_bool_t no_loop = (fport->options & PJMEDIA_FILE_NO_LOOP); 
     645 
     646            if (!fport->subscribed) { 
     647                status = pjmedia_event_subscribe(NULL, &file_on_event, 
     648                                                 fport, fport); 
     649                fport->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     650                                    PJ_FALSE; 
     651            } 
     652 
     653            if (fport->subscribed && fport->eof != 2) { 
     654                pjmedia_event event; 
     655 
     656                if (no_loop) { 
     657                    /* To prevent the callback from being called repeatedly */ 
     658                    fport->eof = 2; 
     659                } else { 
     660                    fport->eof = PJ_FALSE; 
     661                } 
     662 
     663                pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     664                                   NULL, fport); 
     665                pjmedia_event_publish(NULL, fport, &event, 
     666                                      PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     667            } 
     668             
     669            /* Should not access player port after this since 
     670             * it might have been destroyed by the callback. 
     671             */ 
     672            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     673            frame->size = 0; 
     674             
     675            return (no_loop? PJ_EEOF: PJ_SUCCESS); 
     676 
     677        } else if (fport->cb) { 
    598678            status = (*fport->cb)(this_port, fport->base.port_data.pdata); 
     679        } 
    599680 
    600681        /* If callback returns non PJ_SUCCESS or 'no loop' is specified, 
     
    602683         * it might have been destroyed by the callback). 
    603684         */ 
    604         if ((status != PJ_SUCCESS) || (fport->options & PJMEDIA_FILE_NO_LOOP)) { 
     685        if ((status != PJ_SUCCESS) || (fport->options & PJMEDIA_FILE_NO_LOOP)) 
     686        { 
    605687            frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    606688            frame->size = 0; 
    607689            return PJ_EEOF; 
    608690        } 
    609          
     691 
     692        /* Rewind file */ 
    610693        PJ_LOG(5,(THIS_FILE, "File port %.*s rewinding..", 
    611694                  (int)fport->base.info.name.slen, 
    612695                  fport->base.info.name.ptr)); 
    613          
    614696        fport->eof = PJ_FALSE; 
    615697    } 
     
    725807 
    726808    pj_file_close(fport->fd); 
     809 
     810    if (fport->subscribed) { 
     811        pjmedia_event_unsubscribe(NULL, &file_on_event, fport, fport); 
     812        fport->subscribed = PJ_FALSE; 
     813    } 
     814 
    727815    return PJ_SUCCESS; 
    728816} 
  • pjproject/trunk/pjmedia/src/pjmedia/wav_playlist.c

    r5711 r6112  
    7575 
    7676    pj_status_t    (*cb)(pjmedia_port*, void*); 
     77    pj_bool_t        subscribed; 
     78    void           (*cb2)(pjmedia_port*, void*); 
    7779}; 
    7880 
     
    102104 
    103105    return port; 
     106} 
     107 
     108 
     109static pj_status_t file_on_event(pjmedia_event *event, 
     110                                 void *user_data) 
     111{ 
     112    struct playlist_port *fport = (struct playlist_port*)user_data; 
     113 
     114    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     115        if (fport->cb2) 
     116            (*fport->cb2)(&fport->base, fport->base.port_data.pdata); 
     117    } 
     118     
     119    return PJ_SUCCESS; 
    104120} 
    105121 
     
    176192 
    177193                /* All files have been played. Call callback, if any. */ 
    178                 if (fport->cb) 
    179                 { 
     194                if (fport->cb2) { 
     195                    pj_bool_t no_loop = (fport->options & PJMEDIA_FILE_NO_LOOP); 
     196 
     197                    if (!fport->subscribed) { 
     198                        status = pjmedia_event_subscribe(NULL, &file_on_event, 
     199                                                         fport, fport); 
     200                        fport->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     201                                            PJ_FALSE; 
     202                    } 
     203 
     204                    if (fport->subscribed && fport->eof != 2) { 
     205                        pjmedia_event event; 
     206 
     207                        if (no_loop) { 
     208                            /* To prevent the callback from being called 
     209                             * repeatedly. 
     210                             */ 
     211                            fport->eof = 2; 
     212                        } else { 
     213                            fport->eof = PJ_FALSE; 
     214                            /* start with first file again. */ 
     215                            fport->current_file = current_file = 0; 
     216                            fport->fpos_list[0] = fport->start_data_list[0]; 
     217                            pj_file_setpos(fport->fd_list[0], 
     218                                           fport->fpos_list[0], PJ_SEEK_SET); 
     219                            fport->data_left_list[0] = fport->data_len_list[0]; 
     220                        } 
     221 
     222                        pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     223                                           NULL, fport); 
     224                        pjmedia_event_publish(NULL, fport, &event, 
     225                                          PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     226                    } 
     227 
     228                    /* Should not access player port after this since 
     229                     * it might have been destroyed by the callback. 
     230                     */ 
     231                    return (no_loop? PJ_EEOF: PJ_SUCCESS); 
     232 
     233                } else if (fport->cb) { 
    180234                    PJ_LOG(5,(THIS_FILE, 
    181235                              "File port %.*s EOF, calling callback", 
     
    578632 
    579633 
     634#if !DEPRECATED_FOR_TICKET_2251 
    580635/* 
    581636 * Register a callback to be called when the file reading has reached the 
     
    595650    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
    596651 
     652    PJ_LOG(1, (THIS_FILE, "pjmedia_wav_playlist_set_eof_cb() is deprecated. " 
     653               "Use pjmedia_wav_playlist_set_eof_cb2() instead.")); 
     654 
    597655    fport = (struct playlist_port*) port; 
    598656 
    599657    fport->base.port_data.pdata = user_data; 
    600658    fport->cb = cb; 
     659 
     660    return PJ_SUCCESS; 
     661} 
     662#endif 
     663 
     664 
     665/* 
     666 * Register a callback to be called when the file reading has reached the 
     667 * end of the last file. 
     668 */ 
     669PJ_DEF(pj_status_t) pjmedia_wav_playlist_set_eof_cb2(pjmedia_port *port, 
     670                                void *user_data, 
     671                                void (*cb)(pjmedia_port *port, 
     672                                           void *usr_data)) 
     673{ 
     674    struct playlist_port *fport; 
     675 
     676    /* Sanity check */ 
     677    PJ_ASSERT_RETURN(port, PJ_EINVAL); 
     678 
     679    /* Check that this is really a playlist port */ 
     680    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
     681 
     682    fport = (struct playlist_port*) port; 
     683 
     684    fport->base.port_data.pdata = user_data; 
     685    fport->cb2 = cb; 
    601686 
    602687    return PJ_SUCCESS; 
     
    676761    pj_assert(this_port->info.signature == SIGNATURE); 
    677762 
     763    if (fport->subscribed) { 
     764        pjmedia_event_unsubscribe(NULL, &file_on_event, fport, fport); 
     765        fport->subscribed = PJ_FALSE; 
     766    } 
     767 
    678768    for (index=0; index<fport->max_file; index++) 
    679769        pj_file_close(fport->fd_list[index]); 
  • pjproject/trunk/pjmedia/src/pjmedia/wav_writer.c

    r4537 r6112  
    4949    pj_size_t        cb_size; 
    5050    pj_status_t    (*cb)(pjmedia_port*, void*); 
     51    pj_bool_t        subscribed; 
     52    pj_bool_t        cb_called; 
     53    void           (*cb2)(pjmedia_port*, void*); 
    5154}; 
    5255 
     
    245248 
    246249 
     250#if !DEPRECATED_FOR_TICKET_2251 
    247251/* 
    248252 * Register callback. 
     
    262266    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
    263267 
     268    PJ_LOG(1, (THIS_FILE, "pjmedia_wav_writer_port_set_cb() is deprecated. " 
     269               "Use pjmedia_wav_writer_port_set_cb2() instead.")); 
     270 
    264271    fport = (struct file_port*) port; 
    265272 
     
    267274    fport->base.port_data.pdata = user_data; 
    268275    fport->cb = cb; 
     276 
     277    return PJ_SUCCESS; 
     278} 
     279#endif 
     280 
     281 
     282/* 
     283 * Register callback. 
     284 */ 
     285PJ_DEF(pj_status_t) pjmedia_wav_writer_port_set_cb2(pjmedia_port *port, 
     286                                pj_size_t pos, 
     287                                void *user_data, 
     288                                void (*cb)(pjmedia_port *port, 
     289                                           void *usr_data)) 
     290{ 
     291    struct file_port *fport; 
     292 
     293    /* Sanity check */ 
     294    PJ_ASSERT_RETURN(port && cb, PJ_EINVAL); 
     295 
     296    /* Check that this is really a writer port */ 
     297    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
     298 
     299    fport = (struct file_port*) port; 
     300 
     301    fport->cb_size = pos; 
     302    fport->base.port_data.pdata = user_data; 
     303    fport->cb2 = cb; 
     304    fport->cb_called = PJ_FALSE; 
    269305 
    270306    return PJ_SUCCESS; 
     
    302338 
    303339    return status; 
     340} 
     341 
     342static pj_status_t file_on_event(pjmedia_event *event, 
     343                                 void *user_data) 
     344{ 
     345    struct file_port *fport = (struct file_port*)user_data; 
     346 
     347    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     348        if (fport->cb2) 
     349            (*fport->cb2)(&fport->base, fport->base.port_data.pdata); 
     350    } 
     351     
     352    return PJ_SUCCESS; 
    304353} 
    305354 
     
    354403    /* Increment total written, and check if we need to call callback */ 
    355404    fport->total += frame_size; 
    356     if (fport->cb && fport->total >= fport->cb_size) { 
    357         pj_status_t (*cb)(pjmedia_port*, void*); 
    358         pj_status_t status; 
    359  
    360         cb = fport->cb; 
    361         fport->cb = NULL; 
    362  
    363         status = (*cb)(this_port, this_port->port_data.pdata); 
    364         return status; 
     405    if (fport->total >= fport->cb_size) { 
     406        if (fport->cb2) { 
     407            if (!fport->subscribed) { 
     408                pj_status_t status; 
     409 
     410                status = pjmedia_event_subscribe(NULL, &file_on_event, 
     411                                                 fport, fport); 
     412                fport->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     413                                    PJ_FALSE; 
     414            } 
     415 
     416            if (fport->subscribed && !fport->cb_called) { 
     417                pjmedia_event event; 
     418 
     419                /* To prevent the callback from being called more than once. */ 
     420                fport->cb_called = PJ_TRUE; 
     421 
     422                pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     423                                   NULL, fport); 
     424                pjmedia_event_publish(NULL, fport, &event, 
     425                                      PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     426            } 
     427        } else if (fport->cb) { 
     428            pj_status_t (*cb)(pjmedia_port*, void*); 
     429            pj_status_t status; 
     430 
     431            cb = fport->cb; 
     432            fport->cb = NULL; 
     433 
     434            status = (*cb)(this_port, this_port->port_data.pdata); 
     435            return status; 
     436        } 
    365437    } 
    366438 
     
    393465    pj_uint32_t data_len_pos = DATA_LEN_POS; 
    394466 
     467    if (fport->subscribed) { 
     468        pjmedia_event_unsubscribe(NULL, &file_on_event, fport, fport); 
     469        fport->subscribed = PJ_FALSE; 
     470    } 
     471 
    395472    /* Flush remaining buffers. */ 
    396473    if (fport->writepos != fport->buf)  
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r6044 r6112  
    10021002 
    10031003/* Playfile done notification, set timer to hangup calls */ 
    1004 pj_status_t on_playfile_done(pjmedia_port *port, void *usr_data) 
     1004void on_playfile_done(pjmedia_port *port, void *usr_data) 
    10051005{ 
    10061006    pj_time_val delay; 
     
    10121012    if (pjsua_call_get_count() == 0) { 
    10131013        pjsua_player_set_pos(app_config.wav_id, 0); 
    1014         return PJ_SUCCESS; 
    10151014    } 
    10161015 
    10171016    /* Timer is already active */ 
    10181017    if (app_config.auto_hangup_timer.id == 1) 
    1019         return PJ_SUCCESS; 
     1018        return; 
    10201019 
    10211020    app_config.auto_hangup_timer.id = 1; 
     
    10251024                               &app_config.auto_hangup_timer,  
    10261025                               &delay); 
    1027  
    1028     return PJ_SUCCESS; 
    10291026} 
    10301027 
     
    13611358 
    13621359                pjsua_player_get_port(app_config.wav_id, &port); 
    1363                 status = pjmedia_wav_player_set_eof_cb(port, NULL,  
    1364                                                        &on_playfile_done); 
     1360                status = pjmedia_wav_player_set_eof_cb2(port, NULL,  
     1361                                                        &on_playfile_done); 
    13651362                if (status != PJ_SUCCESS) 
    13661363                    goto on_error; 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app_config.c

    r6028 r6112  
    141141    puts  ("                      This can be specified multiple times."); 
    142142    puts  ("  --auto-play         Automatically play the file (to incoming calls only)"); 
     143    puts  ("  --auto-play-hangup  Automatically hangup the file after file play completes"); 
    143144    puts  ("  --auto-loop         Automatically loop incoming RTP to outgoing RTP"); 
    144145    puts  ("  --auto-conf         Automatically put calls in conference with others"); 
  • pjproject/trunk/pjsip-apps/src/samples/footprint.c

    r6071 r6112  
    588588    pjmedia_wav_player_port_set_pos(NULL, 0); 
    589589    pjmedia_wav_player_port_get_pos(NULL); 
    590     pjmedia_wav_player_set_eof_cb(NULL, NULL, NULL); 
     590    pjmedia_wav_player_set_eof_cb2(NULL, NULL, NULL); 
    591591#endif 
    592592 
     
    594594    pjmedia_wav_writer_port_create(NULL, NULL, 8000, 1, 80, 16, 0, 0, NULL); 
    595595    pjmedia_wav_writer_port_get_pos(NULL); 
    596     pjmedia_wav_writer_port_set_cb(NULL, 0, NULL, NULL); 
     596    pjmedia_wav_writer_port_set_cb2(NULL, 0, NULL, NULL); 
    597597#endif 
    598598 
  • pjproject/trunk/pjsip/include/pjsua2/media.hpp

    r6074 r6112  
    549549     */ 
    550550 
     551 
     552/* Unfortunately for pjsua2, a hard deprecation is inevitable. */ 
     553#if 0 // !DEPRECATED_FOR_TICKET_2251 
    551554    /** 
    552555     * Register a callback to be called when the file player reading has 
     
    563566    virtual bool onEof() 
    564567    { return true; } 
    565  
     568#endif 
     569 
     570    /** 
     571     * Register a callback to be called when the file player reading has 
     572     * reached the end of file, or when the file reading has reached the 
     573     * end of file of the last file for a playlist. If the file or playlist 
     574     * is set to play repeatedly, then the callback will be called multiple 
     575     * times. 
     576     * 
     577     * If application wishes to stop the playback, it can stop the media 
     578     * transmission in the callback, and only after all transmissions have 
     579     * been stopped, could the application safely destroy the player. 
     580     */ 
     581    virtual void onEof2() 
     582    { } 
    566583 
    567584private: 
     
    574591     *  Low level PJMEDIA callback 
    575592     */ 
    576     static pj_status_t eof_cb(pjmedia_port *port, 
    577                               void *usr_data); 
     593    static void eof_cb(pjmedia_port *port, 
     594                       void *usr_data); 
    578595}; 
    579596 
  • pjproject/trunk/pjsip/src/pjsua2/media.cpp

    r6074 r6112  
    303303        PJSUA2_RAISE_ERROR2(status, "AudioMediaPlayer::createPlayer()"); 
    304304    } 
    305     status = pjmedia_wav_player_set_eof_cb(port, this, &eof_cb); 
     305    status = pjmedia_wav_player_set_eof_cb2(port, this, &eof_cb); 
    306306    if (status != PJ_SUCCESS) { 
    307307        pjsua_player_destroy(playerId); 
     
    351351        PJSUA2_RAISE_ERROR2(status, "AudioMediaPlayer::createPlaylist()"); 
    352352    } 
    353     status = pjmedia_wav_playlist_set_eof_cb(port, this, &eof_cb); 
     353    status = pjmedia_wav_playlist_set_eof_cb2(port, this, &eof_cb); 
    354354    if (status != PJ_SUCCESS) { 
    355355        pjsua_player_destroy(playerId); 
     
    399399} 
    400400 
    401 pj_status_t AudioMediaPlayer::eof_cb(pjmedia_port *port, 
    402                                      void *usr_data) 
     401void AudioMediaPlayer::eof_cb(pjmedia_port *port, 
     402                              void *usr_data) 
    403403{ 
    404404    PJ_UNUSED_ARG(port); 
    405405    AudioMediaPlayer *player = (AudioMediaPlayer*)usr_data; 
    406     return player->onEof() ? PJ_SUCCESS : PJ_EEOF; 
     406     
     407    player->onEof2(); 
    407408} 
    408409 
  • pjproject/trunk/third_party/mp3/mp3_port.h

    r1177 r6112  
    113113                               pjmedia_port **p_port ); 
    114114 
     115 
     116#if !DEPRECATED_FOR_TICKET_2251 
    115117/** 
    116118 * Register the callback to be called when the file writing has reached 
     
    134136                                void *user_data, 
    135137                                pj_status_t (*cb)(pjmedia_port *port, 
    136                                                         void *usr_data)); 
     138                                                  void *usr_data)); 
     139#endif 
     140 
     141 
     142/** 
     143 * Register the callback to be called when the file writing has reached 
     144 * certain size. Application can use this callback, for example, to limit 
     145 * the size of the output file. 
     146 * 
     147 * @param port          The file writer port. 
     148 * @param pos           The file position on which the callback will be called. 
     149 * @param user_data     User data to be specified in the callback, and will be 
     150 *                      given on the callback. 
     151 * @param cb            Callback to be called. Note that if 
     152 *                      application wishes to stop the playback, it 
     153 *                      can disconnect the port in the callback, and 
     154 *                      only after all connections have been removed 
     155 *                      could the application safely destroy the port. 
     156 * 
     157 * @return              PJ_SUCCESS on success. 
     158 */ 
     159PJ_DECL(pj_status_t)  
     160pjmedia_mp3_writer_port_set_cb2(pjmedia_port *port, 
     161                                pj_size_t pos, 
     162                                void *user_data, 
     163                                void (*cb)(pjmedia_port *port, 
     164                                           void *usr_data)); 
    137165 
    138166 
  • pjproject/trunk/third_party/mp3/mp3_writer.c

    r4483 r6112  
    6262    pj_size_t       cb_size; 
    6363    pj_status_t    (*cb)(pjmedia_port*, void*); 
     64    pj_bool_t        subscribed; 
     65    pj_bool_t        cb_called; 
     66    void           (*cb2)(pjmedia_port*, void*); 
    6467 
    6568    unsigned        silence_duration; 
     
    332335 
    333336 
    334  
     337#if !DEPRECATED_FOR_TICKET_2251 
    335338/* 
    336339 * Register callback. 
     
    351354    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
    352355 
     356    PJ_LOG(1, (THIS_FILE, "pjmedia_mp3_writer_port_set_cb() is deprecated. " 
     357               "Use pjmedia_mp3_writer_port_set_cb2() instead.")); 
     358 
    353359    fport = (struct mp3_file_port*) port; 
    354360 
     
    359365    return PJ_SUCCESS; 
    360366 
     367} 
     368#endif 
     369 
     370 
     371/* 
     372 * Register callback. 
     373 */ 
     374PJ_DEF(pj_status_t)  
     375pjmedia_mp3_writer_port_set_cb2(pjmedia_port *port, 
     376                                pj_size_t pos, 
     377                                void *user_data, 
     378                                void (*cb)(pjmedia_port *port, 
     379                                           void *usr_data)) 
     380{ 
     381    struct mp3_file_port *fport; 
     382 
     383    /* Sanity check */ 
     384    PJ_ASSERT_RETURN(port && cb, PJ_EINVAL); 
     385 
     386    /* Check that this is really a writer port */ 
     387    PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP); 
     388 
     389    fport = (struct mp3_file_port*) port; 
     390 
     391    fport->cb_size = pos; 
     392    fport->base.port_data.pdata = user_data; 
     393    fport->cb2 = cb; 
     394    fport->cb_called = PJ_FALSE; 
     395 
     396    return PJ_SUCCESS; 
     397 
     398} 
     399 
     400 
     401static pj_status_t file_on_event(pjmedia_event *event, 
     402                                 void *user_data) 
     403{ 
     404    struct file_port *fport = (struct file_port*)user_data; 
     405 
     406    if (event->type == PJMEDIA_EVENT_CALLBACK) { 
     407        if (fport->cb2) 
     408            (*fport->cb2)(&fport->base, fport->base.port_data.pdata); 
     409    } 
     410     
     411    return PJ_SUCCESS; 
    361412} 
    362413 
     
    499550    } 
    500551 
    501     /* Increment total written, and check if we need to call callback */ 
    502      
    503     if (fport->cb && fport->total >= fport->cb_size) { 
    504         pj_status_t (*cb)(pjmedia_port*, void*); 
    505         pj_status_t status; 
    506  
    507         cb = fport->cb; 
    508         fport->cb = NULL; 
    509  
    510         status = (*cb)(this_port, this_port->port_data.pdata); 
    511         return status; 
     552    /* Check if we need to call callback */ 
     553    if (fport->total >= fport->cb_size) { 
     554        if (fport->cb2) { 
     555            if (!fport->subscribed) { 
     556                pj_status_t status; 
     557 
     558                status = pjmedia_event_subscribe(NULL, &file_on_event, 
     559                                                 fport, fport); 
     560                fport->subscribed = (status == PJ_SUCCESS)? PJ_TRUE: 
     561                                    PJ_FALSE; 
     562            } 
     563 
     564            if (fport->subscribed && !fport->cb_called) { 
     565                pjmedia_event event; 
     566 
     567                /* To prevent the callback from being called more than once. */ 
     568                fport->cb_called = PJ_TRUE; 
     569 
     570                pjmedia_event_init(&event, PJMEDIA_EVENT_CALLBACK, 
     571                                   NULL, fport); 
     572                pjmedia_event_publish(NULL, fport, &event, 
     573                                      PJMEDIA_EVENT_PUBLISH_POST_EVENT); 
     574            } 
     575        } else if (fport->cb) { 
     576            pj_status_t (*cb)(pjmedia_port*, void*); 
     577            pj_status_t status; 
     578 
     579            cb = fport->cb; 
     580            fport->cb = NULL; 
     581 
     582            status = (*cb)(this_port, this_port->port_data.pdata); 
     583            return status; 
     584        } 
    512585    } 
    513586 
     
    537610    unsigned long MP3Err; 
    538611 
     612    if (fport->subscribed) { 
     613        pjmedia_event_unsubscribe(NULL, &file_on_event, fport, fport); 
     614        fport->subscribed = PJ_FALSE; 
     615    } 
    539616 
    540617    /* Close encoder */ 
Note: See TracChangeset for help on using the changeset viewer.