diff --git a/veejay-current/veejay-client/src/sequence.c b/veejay-current/veejay-client/src/sequence.c index 3c1fa089..d921d332 100644 --- a/veejay-current/veejay-client/src/sequence.c +++ b/veejay-current/veejay-client/src/sequence.c @@ -328,6 +328,8 @@ static int veejay_process_status( veejay_preview_t *vp, veejay_track_t *v ) if( sscanf( status_len+1, "%03d", &bytes ) != 1 ) { veejay_msg(0, "Invalid status message."); bytes = 0; + reloaded_schedule_restart(); + break; } if(bytes > 0 ) diff --git a/veejay-current/veejay-server/libstream/vj-net.c b/veejay-current/veejay-server/libstream/vj-net.c index dd3702e3..781c6e3f 100644 --- a/veejay-current/veejay-server/libstream/vj-net.c +++ b/veejay-current/veejay-server/libstream/vj-net.c @@ -42,12 +42,18 @@ typedef struct { pthread_mutex_t mutex; pthread_t thread; - vj_client *remote; int state; int have_frame; int error; int grab; int repeat; + int w; + int h; + int f; + int in_fmt; + int in_w; + int in_h; + int af; } threaded_t; static void lock_(threaded_t *t, const char *f, int line) @@ -79,16 +85,32 @@ void *reader_thread(void *data) { vj_tag *tag = (vj_tag*) data; threaded_t *t = tag->priv; - vj_client *v = t->remote; int ret = 0; char buf[16]; #ifdef STRICT_CHECKING assert( v != NULL ); #endif - sprintf(buf, "%03d:;", VIMS_GET_FRAME); + snprintf(buf,sizeof(buf)-1, "%03d:;", VIMS_GET_FRAME); int retrieve = 0; + int success = 0; + + vj_client *v = vj_client_alloc( t->w, t->h, t->af ); + v->lzo = lzo_new(); + + success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); + + if( success > 0 ) { + veejay_msg(VEEJAY_MSG_INFO, "Connecton established with %s:%d",tag->source_name, + tag->video_channel + 5); + } + else if ( tag->source_type != VJ_TAG_TYPE_MCAST ) + { + veejay_msg(0, "Unable to connect to %s: %d", tag->source_name, tag->video_channel+5); + pthread_exit(&(t->thread)); + return NULL; + } for( ;; ) { @@ -98,6 +120,9 @@ void *reader_thread(void *data) if( t->state == 0 ) { vj_client_close(v); + veejay_msg(VEEJAY_MSG_INFO, "Closed connection with %s: %d", + tag->source_name,tag->video_channel+5); + vj_client_free(v); pthread_exit( &(t->thread)); return NULL; } @@ -167,6 +192,9 @@ void *reader_thread(void *data) } else { + t->in_fmt = v->in_fmt; + t->in_w = v->in_width; + t->in_h = v->in_height; t->have_frame = ret; t->grab = 1; retrieve =0; @@ -175,7 +203,7 @@ void *reader_thread(void *data) else { if(tag->source_type == VJ_TAG_TYPE_MCAST ) - wait_time = 25; + wait_time = 15; } } unlock(t); @@ -192,7 +220,11 @@ void *reader_thread(void *data) { int success = 0; vj_client_close( v ); - + vj_client_free( v); + v = vj_client_alloc( t->w, t->h, t->af ); + if(!v) { + pthread_exit( &(t->thread)); + } net_delay( 0,3 ); if(tag->source_type == VJ_TAG_TYPE_MCAST ) @@ -231,7 +263,6 @@ void *net_threader( ) int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) { threaded_t *t = (threaded_t*) tag->priv; - vj_client *v = t->remote; const uint8_t *buf = tag->socket_frame; lock(t); @@ -245,13 +276,13 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) } //@ color space convert frame - int len = v->cur_width * v->cur_height; + int len = t->w * t->h; int uv_len = len; - switch(v->cur_fmt) + switch(t->f) { case PIX_FMT_YUV420P: case PIX_FMT_YUVJ420P: - uv_len=len/4; + uv_len=len/4; break; default: uv_len=len/2; @@ -272,16 +303,16 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) VJFrame *a = NULL; VJFrame *b = NULL; - if( v->in_fmt == PIX_FMT_RGB24 || v->in_fmt == PIX_FMT_BGR24 || v->in_fmt == PIX_FMT_RGBA || - v->in_fmt == PIX_FMT_RGB32_1 ) { + if( t->in_fmt == PIX_FMT_RGB24 || t->in_fmt == PIX_FMT_BGR24 || t->in_fmt == PIX_FMT_RGBA || + t->in_fmt == PIX_FMT_RGB32_1 ) { - a = yuv_rgb_template( tag->socket_frame, v->in_width, v->in_width, v->in_fmt ); + a = yuv_rgb_template( tag->socket_frame, t->in_w, t->in_w, t->in_fmt ); } else { - int b_len = v->in_width * v->in_height; + int b_len = t->in_w * t->in_h; int buvlen = b_len; - switch(v->in_fmt) + switch(t->in_fmt) { case PIX_FMT_YUV420P: case PIX_FMT_YUVJ420P: @@ -294,10 +325,10 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) a =yuv_yuv_template( tag->socket_frame, tag->socket_frame + b_len, tag->socket_frame+b_len+buvlen, - v->in_width,v->in_height, v->in_fmt); + t->in_w,t->in_h, t->in_fmt); } - b = yuv_yuv_template( buffer[0],buffer[1], buffer[2],v->cur_width,v->cur_height,v->cur_fmt); + b = yuv_yuv_template( buffer[0],buffer[1], buffer[2],t->w,t->h,t->f); yuv_convert_any_ac(a,b, a->format,b->format ); free(a); free(b); @@ -311,7 +342,6 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h ) { threaded_t *t = (threaded_t*) tag->priv; - vj_client *v = t->remote; const uint8_t *buf = tag->socket_frame; lock(t); @@ -325,9 +355,9 @@ int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h ) } //@ color space convert frame - int len = v->cur_width * v->cur_height; + int len = t->w * t->h; int uv_len = len; - switch(v->cur_fmt) + switch(t->f) { case FMT_420: case FMT_420F: @@ -340,9 +370,9 @@ int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h ) if(t->have_frame ) { - int b_len = v->in_width * v->in_height; + int b_len = t->in_w * t->in_h; int buvlen = b_len; - switch(v->in_fmt) + switch(t->in_fmt) { case FMT_420: case FMT_420F: @@ -353,10 +383,10 @@ int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h ) break; } - int tmp_fmt = get_ffmpeg_pixfmt( v->in_fmt ); + int tmp_fmt = get_ffmpeg_pixfmt( t->in_fmt ); VJFrame *a = yuv_yuv_template( tag->socket_frame, tag->socket_frame + b_len, tag->socket_frame+b_len+buvlen, - v->in_width,v->in_height, tmp_fmt); + t->in_w,t->in_h, tmp_fmt); VJFrame *b = yuv_rgb_template( buffer,w,h,PIX_FMT_RGB24); yuv_convert_any_ac(a,b, a->format,b->format ); free(a); @@ -369,39 +399,44 @@ int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h ) } -int net_thread_start(vj_client *v, vj_tag *tag) +int net_thread_start(vj_tag *tag, int wid, int height, int pixelformat) { int success = 0; int res = 0; - if(tag->source_type == VJ_TAG_TYPE_MCAST ) - success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel ); - else + if(tag->source_type == VJ_TAG_TYPE_MCAST ) { + veejay_msg(0, "MCAST: fixme!"); + } + //@ + // success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel ); +/* else success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); - - if( success <= 0 ) - { - veejay_msg(VEEJAY_MSG_ERROR, "Unable to establish connection with %s on port %d", - tag->source_name, tag->video_channel + 5); - return 0; - } - else - { - veejay_msg(VEEJAY_MSG_INFO, "Connecton established with %s:%d",tag->source_name, - tag->video_channel + 5); - } +*/ threaded_t *t = (threaded_t*)tag->priv; pthread_mutex_init( &(t->mutex), NULL ); - v->lzo = lzo_new(); t->repeat = 0; + t->w = wid; + t->h = height; + t->af = pixelformat; + t->f = get_ffmpeg_pixfmt(pixelformat); t->have_frame = 0; t->error = 0; t->state = 1; - t->remote = v; t->grab = 1; - + + int p_err = pthread_create( &(t->thread), NULL, &reader_thread, (void*) tag ); + if( p_err ==0) + + { + + veejay_msg(VEEJAY_MSG_INFO, "Created new %s threaded stream to veejay host %s port %d", + tag->source_type == VJ_TAG_TYPE_MCAST ? + "multicast" : "unicast", tag->source_name,tag->video_channel); + } + return 1; + /* if( tag->source_type == VJ_TAG_TYPE_MCAST ) { @@ -435,13 +470,13 @@ int net_thread_start(vj_client *v, vj_tag *tag) if( p_err ==0) { - veejay_msg(VEEJAY_MSG_INFO, "Created new %s threaded stream with Veejay host %s port %d", + veejay_msg(VEEJAY_MSG_INFO, "Created new %s threaded stream to veejay host %s port %d", tag->source_type == VJ_TAG_TYPE_MCAST ? "multicast" : "unicast", tag->source_name,tag->video_channel); return 1; } - return 0; +*/ } void net_thread_stop(vj_tag *tag) @@ -449,22 +484,8 @@ void net_thread_stop(vj_tag *tag) char mcast_stop[6]; threaded_t *t = (threaded_t*)tag->priv; int ret = 0; - lock(t); - if(tag->source_type == VJ_TAG_TYPE_MCAST) - { - sprintf(mcast_stop, "%03d:;", VIMS_VIDEO_MCAST_STOP ); - ret = vj_client_send( t->remote , V_CMD, mcast_stop); - if(ret) - veejay_msg(VEEJAY_MSG_INFO, "Stopped multicast stream"); - } - if(tag->source_type == VJ_TAG_TYPE_NET) - { - sprintf(mcast_stop, "%03d:;", VIMS_CLOSE ); - ret = vj_client_send( t->remote, V_CMD, mcast_stop); - if(ret) - veejay_msg(VEEJAY_MSG_INFO, "Stopped unicast stream"); - } + lock(t); t->state = 0; diff --git a/veejay-current/veejay-server/libstream/vj-net.h b/veejay-current/veejay-server/libstream/vj-net.h index 32ac5d7c..b23bdcc6 100644 --- a/veejay-current/veejay-server/libstream/vj-net.h +++ b/veejay-current/veejay-server/libstream/vj-net.h @@ -22,7 +22,7 @@ int net_already_opened(const char *filname, int n, int chan); void net_thread_stop(vj_tag *tag); -int net_thread_start(vj_client *v, vj_tag *tag); +int net_thread_start(vj_tag *tag, int w, int h, int f); void net_thread_remote(void *priv, void *p ); int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3]); int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h); diff --git a/veejay-current/veejay-server/libstream/vj-tag.c b/veejay-current/veejay-server/libstream/vj-tag.c index b841538c..997c7b16 100644 --- a/veejay-current/veejay-server/libstream/vj-tag.c +++ b/veejay-current/veejay-server/libstream/vj-tag.c @@ -357,22 +357,19 @@ int _vj_tag_new_net(vj_tag *tag, int stream_nr, int w, int h,int f, char *host, return 0; } - vj_tag_input->net[stream_nr] = vj_client_alloc(w,h,f); +/* vj_tag_input->net[stream_nr] = vj_client_alloc(w,h,f); v = vj_tag_input->net[stream_nr]; if(!v) { veejay_msg(0, "Memory allocation error while creating network stream"); return 0; - } + }*/ char tmp[255]; bzero(tmp,255); snprintf(tmp,sizeof(tmp)-1, "%s %d", host, port ); tag->extra = (void*) strdup(tmp); - v->planes[0] = w * h; int fmt= vj_tag_input->pix_fmt; - v->planes[1] = v->planes[0] / 2; - v->planes[2] = v->planes[0] / 2; if( tag->socket_ready == 0 ) { @@ -1377,11 +1374,6 @@ int vj_tag_del(int id) case VJ_TAG_TYPE_MCAST: case VJ_TAG_TYPE_NET: net_thread_stop(tag); - if(vj_tag_input->net[tag->index]) - { - vj_client_close( vj_tag_input->net[tag->index] ); - vj_tag_input->net[tag->index] = NULL; - } break; case VJ_TAG_TYPE_COLOR: break; @@ -1392,8 +1384,10 @@ int vj_tag_del(int id) break; case VJ_TAG_TYPE_GENERATOR: if( tag->generator ) { - // plug_deactivate( tag->generator ); + //@ crashes some frei0r plugin, FIXME + //plug_deactivate( tag->generator ); } + tag->generator = NULL; break; } @@ -2607,7 +2601,7 @@ int vj_tag_enable(int t1) { } if(tag->source_type == VJ_TAG_TYPE_NET || tag->source_type == VJ_TAG_TYPE_MCAST ) { - if(!net_thread_start(vj_tag_input->net[tag->index], tag)) + if(!net_thread_start(tag, vj_tag_input->width , vj_tag_input->height, vj_tag_input->pix_fmt)) { veejay_msg(VEEJAY_MSG_ERROR, "Unable to start thread"); diff --git a/veejay-current/veejay-server/libvjnet/cmd.c b/veejay-current/veejay-server/libvjnet/cmd.c index 8719e708..a4482784 100644 --- a/veejay-current/veejay-server/libvjnet/cmd.c +++ b/veejay-current/veejay-server/libvjnet/cmd.c @@ -130,7 +130,7 @@ int sock_t_connect( vj_sock_t *s, char *host, int port ) return 0; } - veejay_msg(VEEJAY_MSG_DEBUG, "Connected to host '%s' port %d", host,port ); + veejay_msg(VEEJAY_MSG_DEBUG, "Connected to host '%s' port %d, fd %d", host,port,s->sock_fd ); return 1; } @@ -157,13 +157,11 @@ int sock_t_poll( vj_sock_t *s ) status = select( s->sock_fd + 1, &(s->rds),&(s->wds), 0, &no_wait ); - if( status == -1 ) + if( status < 0 ) { veejay_msg(VEEJAY_MSG_ERROR, "Unable to poll socket for immediate read: %s", strerror(errno)); return -1; } -// if( status == 0 ) -// return -1; if( sock_t_rds_isset( s ) ) return 1; @@ -239,11 +237,13 @@ int sock_t_send( vj_sock_t *s, unsigned char *buf, int len ) int n; #ifdef STRICT_CHECKING assert( buf != NULL ); -#endif -/* if( sock_t_wds_isset( s ) == 0 ) { - veejay_msg(VEEJAY_MSG_DEBUG, "%s", __FUNCTION__); + + if( sock_t_wds_isset( s ) == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "%s: socket %d", __FUNCTION__, s->sock_fd); + assert(sock_t_wds_isset(s) == 0); return 0; - }*/ + } +#endif int length = len; int bw = 0; @@ -287,7 +287,7 @@ int sock_t_send_fd( int fd, int send_size, unsigned char *buf, int len ) if( n == 0 ) { veejay_msg(VEEJAY_MSG_DEBUG, "Remote closed connection."); - return 0; + return -1; } ptr += n; //@ advance ptr by bytes send @@ -308,8 +308,13 @@ void sock_t_close( vj_sock_t *s ) { if(s) { - close(s->sock_fd); +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "\tclosing socket %d", s->sock_fd ); +#endif + if( s->sock_fd > 0 ) + close(s->sock_fd); s->sock_fd = -1; + FD_ZERO(&(s->rds)); FD_ZERO(&(s->wds)); } diff --git a/veejay-current/veejay-server/libvjnet/vj-client.c b/veejay-current/veejay-server/libvjnet/vj-client.c index fe06c2ec..980d41a4 100644 --- a/veejay-current/veejay-server/libvjnet/vj-client.c +++ b/veejay-current/veejay-server/libvjnet/vj-client.c @@ -49,7 +49,7 @@ #define VJC_SOCKET 2 #define VJC_BAD_HOST 3 -#define PACKET_LEN (65535*32) +#define PACKET_LEN (65535*2) vj_client *vj_client_alloc( int w, int h, int f ) { @@ -164,16 +164,14 @@ int vj_client_connect_dat(vj_client *v, char *host, int port_id ) v->c[0]->type = VSOCK_C; v->c[0]->fd = alloc_sock_t(); - if(v->c[1]) - free(v->c[1]); - - v->c[1] = NULL; - if( sock_t_connect( v->c[0]->fd, host, (port_id + 5) ) ) { veejay_msg(VEEJAY_MSG_INFO, "Connect to DAT port %d", port_id + 5); return 1; } + + v->c[1]->fd = -1; + return error; } @@ -683,18 +681,23 @@ int vj_client_close( vj_client *v ) { if(v->c[0]) { - if(v->c[0]->type == VSOCK_C) + if(v->c[0]->type == VSOCK_C && v->c[0]->fd > 0) { sock_t_close(v->c[0]->fd ); - else if ( v->c[0]->type == VMCAST_C ) + v->c[0]->fd = -1; + } + else if ( v->c[0]->type == VMCAST_C && v->c[0]->fd > 0) { mcast_close_receiver( v->c[0]->r ); mcast_close_sender( v->c[0]->s ); + v->c[0]->fd = -1; } } if(v->c[1]) { - if(v->c[1]->type == VSOCK_S) + if(v->c[1]->type == VSOCK_S && v->c[1]->fd > 0) { sock_t_close(v->c[1]->fd ); + v->c[1]->fd = -1; + } } return 1; diff --git a/veejay-current/veejay-server/libvjnet/vj-server.c b/veejay-current/veejay-server/libvjnet/vj-server.c index aff67158..386dffa7 100644 --- a/veejay-current/veejay-server/libvjnet/vj-server.c +++ b/veejay-current/veejay-server/libvjnet/vj-server.c @@ -567,7 +567,12 @@ int _vj_server_new_client(vj_server *vje, int socket_fd) int _vj_server_del_client(vj_server * vje, int link_id) { vj_link **Link = (vj_link**) vje->link; + if(!Link[link_id]->in_use) { + return 0; + } + Link[link_id]->in_use = 0; + if(Link[link_id]->handle > 0) { int res = close(Link[link_id]->handle); @@ -588,6 +593,9 @@ int _vj_server_del_client(vj_server * vje, int link_id) Link[link_id]->promote = 0; Link[link_id]->n_queued = 0; Link[link_id]->n_retrieved = 0; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG,"Link %d: closed socket %d", link_id, Link[link_id]->handle ); +#endif return 1; } @@ -644,12 +652,9 @@ int vj_server_poll(vj_server * vje) vj_link **Link= (vj_link**) vje->link; if( Link[i]->handle <= 0 || !Link[i]->in_use ) continue; - // if( Link[i]->in_use ) - // { - FD_SET( Link[i]->handle, &(vje->fds) ); - FD_SET( Link[i]->handle, &(vje->wds) ); -// FD_SET( Link[i]->handle, &(vje->eds) ); - // } + FD_SET( Link[i]->handle, &(vje->fds) ); + FD_SET( Link[i]->handle, &(vje->wds) ); + FD_SET( Link[i]->handle, &(vje->eds) ); } status = select(vje->nr_of_connections + 1, &(vje->fds), &(vje->wds), NULL, &t); @@ -975,7 +980,7 @@ int vj_server_new_connection(vj_server *vje) #endif - FD_CLR( vje->handle, &(vje->fds) ); + FD_CLR( fd, &(vje->fds) ); return 1; } return 0; diff --git a/veejay-current/veejay-server/veejay/vj-event.c b/veejay-current/veejay-server/veejay/vj-event.c index 9314e62b..171308c1 100644 --- a/veejay-current/veejay-server/veejay/vj-event.c +++ b/veejay-current/veejay-server/veejay/vj-event.c @@ -1693,10 +1693,10 @@ void vj_event_update_remote(void *ptr) if( p3 ) has_n += vj_server_new_connection( v->vjs[VEEJAY_PORT_DAT] ); - if( has_n ) - { - return; - } +// if( has_n ) +// { +// return; +// } if( v->settings->use_vims_mcast ) { @@ -1732,14 +1732,11 @@ void vj_event_update_remote(void *ptr) vj_event_parse_msg( v, buf,len ); n++; } - } - if( res <= 0 ) - // if( res == -1 ) + }else if( res <= 0 ) { _vj_server_del_client( v->vjs[VEEJAY_PORT_CMD], i ); _vj_server_del_client( v->vjs[VEEJAY_PORT_STA], i ); - if( v->vjs[VEEJAY_PORT_DAT] ) - _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], i ); + // _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], i ); } } } @@ -1761,18 +1758,18 @@ void vj_event_update_remote(void *ptr) vj_event_parse_msg( v, buf,len ); n++; } - } - if( res <= 0 ) - //if( res == -1 ) + } else if( res <= 0 ) { - if( v->vjs[VEEJAY_PORT_DAT] ) - _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], i ); - _vj_server_del_client( v->vjs[VEEJAY_PORT_CMD], i ); - _vj_server_del_client( v->vjs[VEEJAY_PORT_STA], i ); + _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], i ); + // _vj_server_del_client( v->vjs[VEEJAY_PORT_CMD], i ); + // _vj_server_del_client( v->vjs[VEEJAY_PORT_STA], i ); } } } + v->settings->is_dat = 0; + + //@ repeat macros if(macro_status_ == 2 && macro_port_ != NULL) { @@ -1787,9 +1784,6 @@ void vj_event_update_remote(void *ptr) } - v->settings->is_dat = 0; - - if(!veejay_keep_messages()) veejay_reap_messages(); @@ -2713,8 +2707,11 @@ void vj_event_linkclose(void *ptr, const char format[], va_list ap) veejay_t *v = (veejay_t*)ptr; veejay_msg(VEEJAY_MSG_INFO, "Remote requested session-end, quitting Client"); int i = v->uc->current_link; + if( v->vjs[0] ) _vj_server_del_client( v->vjs[0], i ); + if( v->vjs[1] ) _vj_server_del_client( v->vjs[1], i ); + if( v->vjs[2] ) _vj_server_del_client( v->vjs[3], i ); } @@ -8292,7 +8289,6 @@ void vj_event_send_track_list ( void *ptr, const char format[], va_list ap ) int n = vj_tag_size()-1; if (n >= 1 ) { - char line[300]; char *print_buf = get_print_buf(SEND_BUF); int i; for(i=0; i <= n; i++) @@ -8304,8 +8300,8 @@ void vj_event_send_track_list ( void *ptr, const char format[], va_list ap ) { char cmd[275]; char space[275]; - sprintf(space, "%s %d", tag->descr, tag->id ); - sprintf(cmd, "%03d%s",strlen(space),space); + snprintf(space,sizeof(space)-1,"%s %d", tag->descr, tag->id ); + snprintf(cmd,sizeof(cmd)-1,"%03d%s",strlen(space),space); APPEND_MSG(print_buf,cmd); } } @@ -9164,7 +9160,6 @@ void vj_event_send_frame ( void *ptr, const char format[], va_list ap ) return; } - veejay_msg(VEEJAY_MSG_DEBUG, "Will send frame %ld to link %d soon", v->settings->current_frame_num, v->uc->current_link ); v->settings->unicast_frame_sender = 1; }