1 /*****************************************************************************
2 * cddax.c : CD digital audio input module for vlc using libcdio
3 *****************************************************************************
4 * Copyright (C) 2000,2003 VideoLAN
5 * $Id: cddax.c,v 1.9 2003/11/25 03:54:33 rocky Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@netcourrier.com>
9 * Rocky Bernstein <rocky@panix.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
34 #include <vlc/input.h>
35 #include <sys/types.h>
36 #include <cdio/cdio.h>
37 #include <cdio/cd_types.h>
48 #include "vcdx/cdrom.h"
50 /* how many blocks CDDAOpen will read in each loop */
51 #define CDDA_BLOCKS_ONCE 1
52 #define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)
54 /*****************************************************************************
55 * cdda_data_t: CD audio information
56 *****************************************************************************/
57 typedef struct cdda_data_s
59 cddev_t *p_cddev; /* CD device descriptor */
60 int i_nb_tracks; /* Nb of tracks (titles) */
61 int i_track; /* Current track */
62 lsn_t i_sector; /* Current Sector */
63 lsn_t * p_sectors; /* Track sectors */
64 vlc_bool_t b_end_of_track; /* If the end of track was reached */
65 int i_debug; /* Debugging mask */
66 intf_thread_t *p_intf;
70 /*****************************************************************************
72 *****************************************************************************/
73 #define INPUT_DBG_MRL 1
74 #define INPUT_DBG_EVENT 2 /* Trace keyboard events */
75 #define INPUT_DBG_EXT 4 /* Calls from external routines */
76 #define INPUT_DBG_CALL 8 /* all calls */
77 #define INPUT_DBG_LSN 16 /* LSN changes */
78 #define INPUT_DBG_CDIO 32 /* Debugging from CDIO */
79 #define INPUT_DBG_SEEK 64 /* Seeks to set location */
81 #define DEBUG_TEXT N_("set debug mask for additional debugging.")
82 #define DEBUG_LONGTEXT N_( \
83 "This integer when viewed in binary is a debugging mask\n" \
92 #define DEV_TEXT N_("CD-ROM device name")
93 #define DEV_LONGTEXT N_( \
94 "Specify the name of the CD-ROM device that will be used by default. " \
95 "If you don't specify anything, we'll scan for a suitable CD-ROM device.")
99 #define dbg_print(mask, s, args...) \
100 if (p_cdda->i_debug & mask) \
101 msg_Dbg(p_input, "%s: "s, __func__ , ##args)
103 #define dbg_print(mask, s, args...)
106 /*****************************************************************************
107 * intf_sys_t: description and status of interface
108 *****************************************************************************/
111 input_thread_t * p_input;
112 cdda_data_t * p_cdda;
113 vlc_bool_t b_click, b_move, b_key_pressed;
116 /* FIXME: This variable is a hack. Would be nice to eliminate. */
117 static input_thread_t *p_cdda_input = NULL;
119 /*****************************************************************************
121 *****************************************************************************/
122 static int CDDAOpen ( vlc_object_t * );
123 static void CDDAClose ( vlc_object_t * );
124 static int CDDARead ( input_thread_t *, byte_t *, size_t );
125 static void CDDASeek ( input_thread_t *, off_t );
126 static int CDDASetArea ( input_thread_t *, input_area_t * );
127 static int CDDAPlay ( input_thread_t *, int );
128 static int CDDASetProgram ( input_thread_t *, pgrm_descriptor_t * );
130 static int CDDAOpenIntf ( vlc_object_t * );
131 static void CDDACloseIntf ( vlc_object_t * );
134 static int InitThread ( intf_thread_t *p_intf );
135 static int KeyEvent ( vlc_object_t *, char const *,
136 vlc_value_t, vlc_value_t, void * );
138 static void RunIntf ( intf_thread_t *p_intf );
140 static int debug_callback ( vlc_object_t *p_this, const char *psz_name,
141 vlc_value_t oldval, vlc_value_t val,
144 /*****************************************************************************
146 *****************************************************************************/
148 static int DemuxOpen ( vlc_object_t * );
149 static void DemuxClose ( vlc_object_t * );
151 #define CACHING_TEXT N_("Caching value in ms")
152 #define CACHING_LONGTEXT N_( \
153 "Allows you to modify the default caching value for cdda streams. This " \
154 "value should be set in miliseconds units." )
157 set_description( _("CD Audio input") );
158 set_capability( "access", 75 /* slightly higher than cdda */ );
159 add_integer( "cddax-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
160 set_callbacks( CDDAOpen, CDDAClose );
161 add_shortcut( "cdda" );
163 /* Configuration options */
164 add_category_hint( N_("CDX"), NULL, VLC_TRUE );
165 add_integer ( MODULE_STRING "-debug", 0, debug_callback, DEBUG_TEXT,
166 DEBUG_LONGTEXT, VLC_TRUE );
167 add_string( MODULE_STRING "-device", "", NULL, DEV_TEXT,
168 DEV_LONGTEXT, VLC_TRUE );
171 set_description( _("CD Audio demux") );
172 set_capability( "demux", 0 );
173 set_callbacks( DemuxOpen, DemuxClose );
174 add_shortcut( "cdda" );
177 set_capability( "interface", 0 );
178 set_callbacks( E_(CDDAOpenIntf), E_(CDDACloseIntf) );
182 /****************************************************************************
184 ****************************************************************************/
187 debug_callback ( vlc_object_t *p_this, const char *psz_name,
188 vlc_value_t oldval, vlc_value_t val, void *p_data )
192 if (NULL == p_cdda_input) return VLC_EGENERIC;
194 p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
196 if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
197 msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
198 p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int);
200 p_cdda->i_debug = val.i_int;
204 /* process messages that originate from libcdio. */
206 cdio_log_handler (cdio_log_level_t level, const char message[])
208 cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
212 if (p_cdda->i_debug & INPUT_DBG_CDIO)
213 msg_Dbg( p_cdda_input, message);
216 msg_Warn( p_cdda_input, message);
219 case CDIO_LOG_ASSERT:
220 msg_Err( p_cdda_input, message);
223 msg_Warn( p_cdda_input, message,
224 _("The above message had unknown vcdimager log level"),
231 /*****************************************************************************
232 * CDDAOpen: open cdda
233 *****************************************************************************/
234 static int CDDAOpen( vlc_object_t *p_this )
236 input_thread_t * p_input = (input_thread_t *)p_this;
240 cdda_data_t * p_cdda;
245 /* Set where to log errors messages from libcdio. */
246 p_cdda_input = (input_thread_t *)p_this;
248 /* parse the options passed in command line : */
249 psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
256 while( *psz_parser && *psz_parser != '@' )
261 if( *psz_parser == '@' )
267 if ('T' == *psz_parser || 't' == *psz_parser )
270 i_title = (int)strtol( psz_parser, NULL, 10 );
271 i_title = i_title ? i_title : 1;
275 /* No source specified, so figure it out. */
276 if( !p_input->psz_access ) {
280 psz_source = config_GetPsz( p_input, MODULE_STRING "-device" );
282 if( !psz_source || 0==strlen(psz_source) ) {
283 /* Scan for a CD-ROM drive with a CD-DA in it. */
285 cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
286 if (NULL == cd_drives) return -1;
287 if (cd_drives[0] == NULL) {
288 cdio_free_device_list(cd_drives);
291 psz_source = strdup(cd_drives[0]);
292 cdio_free_device_list(cd_drives);
297 cdio_log_set_handler ( cdio_log_handler );
299 if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
301 msg_Warn( p_input, "could not open %s", psz_source );
307 p_cdda = malloc( sizeof(cdda_data_t) );
310 msg_Err( p_input, "out of memory" );
315 p_cdda->p_cddev = p_cddev;
316 p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
317 p_input->p_access_data = (void *)p_cdda;
319 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
321 p_input->i_mtu = CDDA_DATA_ONCE;
323 /* We read the Table Of Content information */
324 p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
325 p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
326 if( p_cdda->i_nb_tracks < 0 )
327 msg_Err( p_input, "unable to count tracks" );
328 else if( p_cdda->i_nb_tracks <= 0 )
329 msg_Err( p_input, "no audio tracks found" );
331 if( p_cdda->i_nb_tracks <= 1)
333 ioctl_Close( p_cdda->p_cddev );
338 if( i_title >= p_cdda->i_nb_tracks || i_title < 1 )
341 /* Set stream and area data */
342 vlc_mutex_lock( &p_input->stream.stream_lock );
344 /* Initialize ES structures */
345 input_InitStream( p_input, 0 );
347 /* cdda input method */
348 p_input->stream.i_method = INPUT_METHOD_CDDA;
350 p_input->stream.b_pace_control = 1;
351 p_input->stream.b_seekable = 1;
352 p_input->stream.i_mux_rate = 44100 * 4 / 50;
354 #define area p_input->stream.pp_areas
355 for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
357 input_AddArea( p_input, i, 1 );
359 /* Absolute start offset and size */
361 (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
363 (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
364 * (off_t)CDIO_CD_FRAMESIZE_RAW;
368 CDDAPlay( p_input, i_title);
370 vlc_mutex_unlock( &p_input->stream.stream_lock );
372 if( !p_input->psz_demux || !*p_input->psz_demux )
374 p_input->psz_demux = "cdda";
377 p_input->pf_read = CDDARead;
378 p_input->pf_seek = CDDASeek;
379 p_input->pf_set_area = CDDASetArea;
380 p_input->pf_set_program = CDDASetProgram;
382 /* Update default_pts to a suitable value for cdda access */
383 p_input->i_pts_delay = config_GetInt( p_input,
384 MODULE_STRING "-caching" ) * 1000;
386 p_cdda->p_intf = intf_Create( p_input, "cddax" );
387 intf_RunThread( p_cdda->p_intf );
392 /*****************************************************************************
393 * CDDAPlay: Arrange things play track
394 *****************************************************************************/
396 CDDAPlay( input_thread_t *p_input, int i_track )
398 cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
400 if( i_track >= p_cdda->i_nb_tracks || i_track < 1 )
403 CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
407 /*****************************************************************************
408 * CDDAClose: closes cdda
409 *****************************************************************************/
411 CDDAClose( vlc_object_t *p_this )
413 input_thread_t * p_input = (input_thread_t *)p_this;
414 cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
416 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
417 ioctl_Close( p_cdda->p_cddev );
422 /*****************************************************************************
423 * CDDARead: reads from the CDDA into PES packets.
424 *****************************************************************************
425 * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
427 *****************************************************************************/
428 static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
431 cdda_data_t * p_cdda;
436 p_cdda = (cdda_data_t *)p_input->p_access_data;
440 /* Compute the number of blocks we have to read */
442 i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
444 for ( i_index = 0; i_index < i_blocks; i_index++ )
447 if (cdio_read_audio_sector(p_cdda->p_cddev->cdio, p_buffer,
448 p_cdda->i_sector) != 0)
450 msg_Err( p_input, "could not read sector %d", p_cdda->i_sector );
455 if ( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
457 input_area_t *p_area;
459 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL),
460 "end of track, cur: %u", p_cdda->i_sector );
462 if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )
465 vlc_mutex_lock( &p_input->stream.stream_lock );
466 p_area = p_input->stream.pp_areas[
467 p_input->stream.p_selected_area->i_id + 1 ];
470 CDDASetArea( p_input, p_area );
471 vlc_mutex_unlock( &p_input->stream.stream_lock );
473 i_read += CDIO_CD_FRAMESIZE_RAW;
476 if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
478 msg_Err( p_input, "must read full sectors" );
484 /*****************************************************************************
485 * CDDASetProgram: Does nothing since a CDDA is mono_program
486 *****************************************************************************/
487 static int CDDASetProgram( input_thread_t * p_input,
488 pgrm_descriptor_t * p_program)
490 cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
491 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
495 /*****************************************************************************
496 * CDDASetArea: initialize input data for title x.
497 * It should be called for each user navigation request.
498 ****************************************************************************/
499 static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
501 cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
504 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
506 /* we can't use the interface slider until initilization is complete */
507 p_input->stream.b_seekable = 0;
509 if( p_area != p_input->stream.p_selected_area )
511 /* Change the default area */
512 p_input->stream.p_selected_area = p_area;
514 /* Change the current track */
515 p_cdda->i_track = p_area->i_id - 1;
516 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
518 /* Update the navigation variables without triggering a callback */
519 val.i_int = p_area->i_id;
520 var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
523 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
525 p_input->stream.p_selected_area->i_tell =
526 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
527 - p_input->stream.p_selected_area->i_start;
529 /* warn interface that something has changed */
530 p_input->stream.b_seekable = 1;
531 p_input->stream.b_changed = 1;
536 /****************************************************************************
538 ****************************************************************************/
539 static void CDDASeek( input_thread_t * p_input, off_t i_off )
541 cdda_data_t * p_cdda;
543 p_cdda = (cdda_data_t *) p_input->p_access_data;
545 p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
546 + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
548 vlc_mutex_lock( &p_input->stream.stream_lock );
549 p_input->stream.p_selected_area->i_tell =
550 (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
551 - p_input->stream.p_selected_area->i_start;
553 vlc_mutex_unlock( &p_input->stream.stream_lock );
555 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
556 "sector %ud, offset: %lld, i_tell: %lld", p_cdda->i_sector, i_off,
557 p_input->stream.p_selected_area->i_tell );
561 /*****************************************************************************
562 * Demux: local prototypes
563 *****************************************************************************/
570 static int Demux ( input_thread_t * p_input );
572 /****************************************************************************
574 ****************************************************************************/
575 static int DemuxOpen ( vlc_object_t * p_this)
577 input_thread_t *p_input = (input_thread_t *)p_this;
582 if( p_input->stream.i_method != INPUT_METHOD_CDDA )
587 p_input->pf_demux = Demux;
588 p_input->pf_rewind = NULL;
589 p_input->pf_demux_control = demux_vaControlDefault;
590 p_input->p_demux_data = p_sys = malloc( sizeof( es_descriptor_t ) );
593 vlc_mutex_lock( &p_input->stream.stream_lock );
594 if( input_InitStream( p_input, 0 ) == -1)
596 vlc_mutex_unlock( &p_input->stream.stream_lock );
597 msg_Err( p_input, "cannot init stream" );
601 p_input->stream.i_mux_rate = 4 * 44100 / 50;
602 vlc_mutex_unlock( &p_input->stream.stream_lock );
604 es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', 'r', 'a', 'w' ) );
605 fmt.audio.i_channels = 2;
606 fmt.audio.i_rate = 44100;
607 fmt.audio.i_bitspersample = 16;
608 fmt.audio.i_blockalign = 4;
609 fmt.i_bitrate = 4 * 44100 * 8;
611 p_sys->p_es = es_out_Add( p_input->p_es_out, &fmt );
616 /****************************************************************************
618 ****************************************************************************/
619 static void DemuxClose( vlc_object_t * p_this)
621 input_thread_t *p_input = (input_thread_t*)p_this;
622 demux_sys_t *p_sys = (demux_sys_t*)p_input->p_demux_data;
628 /****************************************************************************
630 ****************************************************************************/
631 static int Demux( input_thread_t * p_input )
633 demux_sys_t *p_sys = (demux_sys_t*)p_input->p_demux_data;
637 input_ClockManageRef( p_input,
638 p_input->stream.p_selected_program,
641 if( ( p_block = stream_Block( p_input->s, CDIO_CD_FRAMESIZE_RAW ) ) == NULL )
647 p_block->i_pts = input_ClockGetTS( p_input,
648 p_input->stream.p_selected_program,
650 p_block->i_length = (mtime_t)90000 * (mtime_t)p_block->i_buffer/44100/4;
652 p_sys->i_pts += p_block->i_length;
654 es_out_Send( p_input->p_es_out, p_sys->p_es, p_block );
659 /*****************************************************************************
660 * OpenIntf: initialize dummy interface
661 *****************************************************************************/
662 int CDDAOpenIntf ( vlc_object_t *p_this )
664 intf_thread_t *p_intf = (intf_thread_t *)p_this;
666 /* Allocate instance and initialize some members */
667 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
668 if( p_intf->p_sys == NULL )
673 p_intf->pf_run = RunIntf;
675 var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
680 /*****************************************************************************
681 * CloseIntf: destroy dummy interface
682 *****************************************************************************/
683 void CDDACloseIntf ( vlc_object_t *p_this )
685 intf_thread_t *p_intf = (intf_thread_t *)p_this;
687 /* Destroy structure */
688 free( p_intf->p_sys );
692 /*****************************************************************************
694 *****************************************************************************/
695 static void RunIntf( intf_thread_t *p_intf )
697 vlc_object_t * p_vout = NULL;
698 cdda_data_t * p_cdda;
699 input_thread_t * p_input;
701 /* What you add to the last input number entry. It accumulates all of
702 the 10_ADD keypresses */
703 int number_addend = 0;
705 if( InitThread( p_intf ) < 0 )
707 msg_Err( p_intf, "can't initialize intf" );
711 p_input = p_intf->p_sys->p_input;
712 p_cdda = p_intf->p_sys->p_cdda =
713 (cdda_data_t *) p_input->p_access_data;
715 dbg_print( INPUT_DBG_CALL, "intf initialized" );
718 while( !p_intf->b_die )
720 vlc_mutex_lock( &p_intf->change_lock );
725 if( p_vout && p_intf->p_sys->b_key_pressed )
728 int i, i_action = -1;
729 struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys;
731 p_intf->p_sys->b_key_pressed = VLC_FALSE;
733 /* Find action triggered by hotkey (if any) */
734 var_Get( p_intf->p_vlc, "key-pressed", &val );
736 dbg_print( INPUT_DBG_EVENT, "Key pressed %d", val.i_int );
738 for( i = 0; p_hotkeys[i].psz_action != NULL; i++ )
740 if( p_hotkeys[i].i_key == val.i_int )
742 i_action = p_hotkeys[i].i_action;
746 if( i_action != -1) {
749 case ACTIONID_NAV_LEFT:
750 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_LEFT (%d)",
753 if ( CDDAPlay( p_input, p_cdda->i_track-1 ) ) {
758 } while (number_addend-- > 0);
761 case ACTIONID_NAV_RIGHT:
762 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_RIGHT (%d)",
765 if ( CDDAPlay( p_input, p_cdda->i_track+1 ) ) {
770 } while (number_addend-- > 0);
773 case ACTIONID_NAV_UP:
774 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_UP" );
777 } while (number_addend-- > 0);
780 case ACTIONID_NAV_DOWN:
781 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_DOWN" );
784 case ACTIONID_NAV_ACTIVATE:
786 dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_ACTIVATE" );
787 if ( CDDAPlay( p_input, number_addend ) ) {
788 p_cdda->i_track = number_addend;
797 unsigned int digit_entered=0;
821 number_addend += digit_entered;
822 dbg_print( INPUT_DBG_EVENT,
823 "Added %d. Number is now: %d\n",
824 digit_entered, number_addend);
832 vlc_mutex_unlock( &p_intf->change_lock );
836 p_vout = vlc_object_find( p_intf->p_sys->p_input,
837 VLC_OBJECT_VOUT, FIND_ANYWHERE );
840 var_AddCallback( p_vout, "key-pressed", KeyEvent, p_intf );
846 msleep( INTF_IDLE_SLEEP );
851 var_DelCallback( p_vout, "key-pressed", KeyEvent, p_intf );
852 vlc_object_release( p_vout );
855 vlc_object_release( p_intf->p_sys->p_input );
858 /*****************************************************************************
860 *****************************************************************************/
861 static int InitThread( intf_thread_t * p_intf )
863 /* We might need some locking here */
866 input_thread_t * p_input;
868 p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
870 /* Maybe the input just died */
871 if( p_input == NULL )
876 vlc_mutex_lock( &p_intf->change_lock );
878 p_intf->p_sys->p_input = p_input;
880 p_intf->p_sys->b_move = VLC_FALSE;
881 p_intf->p_sys->b_click = VLC_FALSE;
882 p_intf->p_sys->b_key_pressed = VLC_FALSE;
884 vlc_mutex_unlock( &p_intf->change_lock );
894 /*****************************************************************************
895 * KeyEvent: callback for keyboard events
896 *****************************************************************************/
897 static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
898 vlc_value_t oldval, vlc_value_t newval, void *p_data )
900 intf_thread_t *p_intf = (intf_thread_t *)p_data;
901 vlc_mutex_lock( &p_intf->change_lock );
903 p_intf->p_sys->b_key_pressed = VLC_TRUE;
905 vlc_mutex_unlock( &p_intf->change_lock );