#define RECONNECT_LONGTEXT N_("Will automatically attempt a re-connection " \
"in case it was untimely closed.")
+#define CONTINUOUS_TEXT N_("Continuous stream")
+#define CONTINUOUS_LONGTEXT N_("Enable this option to read a file that is " \
+ "being constantly updated (for example, a JPG file on a server)")
+
vlc_module_begin();
set_description( _("HTTP input") );
set_capability( "access2", 0 );
AGENT_LONGTEXT, VLC_FALSE );
add_bool( "http-reconnect", 0, NULL, RECONNECT_TEXT,
RECONNECT_LONGTEXT, VLC_TRUE );
+ add_bool( "http-continuous", 0, NULL, CONTINUOUS_TEXT,
+ CONTINUOUS_LONGTEXT, VLC_TRUE );
add_shortcut( "http" );
add_shortcut( "http4" );
add_shortcut( "http6" );
+ add_shortcut( "unsv" );
set_callbacks( Open, Close );
vlc_module_end();
char *psz_icy_genre;
char *psz_icy_title;
+ int i_remaining;
+
vlc_bool_t b_seekable;
vlc_bool_t b_reconnect;
+ vlc_bool_t b_continuous;
vlc_bool_t b_pace_control;
};
/* */
static void ParseURL( access_sys_t *, char *psz_url );
static int Connect( access_t *, int64_t );
+static int Request( access_t *p_access, int64_t i_tell );
/*****************************************************************************
* Open:
p_sys->psz_icy_name = NULL;
p_sys->psz_icy_genre = NULL;
p_sys->psz_icy_title = NULL;
+ p_sys->i_remaining = 0;
/* Parse URI */
ParseURL( p_sys, p_access->psz_path );
}
p_sys->b_reconnect = var_CreateGetBool( p_access, "http-reconnect" );
+ p_sys->b_continuous = var_CreateGetBool( p_access, "http-continuous" );
/* Connect */
if( Connect( p_access, 0 ) )
return 0;
}
}
+
if( p_sys->b_chunked )
{
if( p_sys->i_chunk < 0 )
}
}
+ if( p_sys->b_continuous && i_len > p_sys->i_remaining )
+ {
+ /* Only ask for the remaining length */
+ int i_new_len = p_sys->i_remaining;
+ if( i_new_len == 0 )
+ {
+ Request( p_access, 0 );
+ i_read = Read( p_access, p_buffer, i_len );
+ return i_read;
+ }
+ i_len = i_new_len;
+ }
+
if( p_sys->i_icy_meta > 0 && p_access->info.i_pos > 0 )
{
- int64_t i_next = p_sys->i_icy_meta -
+ int64_t i_next = p_sys->i_icy_meta -
p_access->info.i_pos % p_sys->i_icy_meta;
-
+
if( i_next == p_sys->i_icy_meta )
{
if( ReadICYMeta( p_access ) )
}
i_read = net_Read( p_access, p_sys->fd, NULL, p_buffer, i_len, VLC_FALSE );
+
if( i_read > 0 )
{
p_access->info.i_pos += i_read;
}
else if( i_read == 0 )
{
+ if( p_sys->b_continuous )
+ {
+ Request( p_access, 0 );
+ p_sys->b_continuous = VLC_FALSE;
+ i_read = Read( p_access, p_buffer, i_len );
+ p_sys->b_continuous = VLC_TRUE;
+ }
if( p_sys->b_reconnect )
{
msg_Dbg( p_access, "got disconnected, trying to reconnect" );
if( i_read == 0 ) p_access->info.b_eof = VLC_TRUE;
}
+ if( p_sys->b_continuous )
+ {
+ p_sys->i_remaining -= i_read;
+ }
+
return i_read;
}
return VLC_EGENERIC;
}
+ return Request( p_access,i_tell );
+}
+
+
+static int Request( access_t *p_access, int64_t i_tell )
+{
+ access_sys_t *p_sys = p_access->p_sys;
+ char *psz;
if( p_sys->b_proxy )
{
if( p_sys->url.psz_path )
p_sys->url.i_port );
}
else
- {
+ {
net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
"GET %s HTTP/1.%d\r\nHost: %s\r\n",
psz_path, p_sys->i_version, p_sys->url.psz_host );
net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
"Range: bytes="I64Fd"-\r\n", i_tell );
}
+
/* Authentification */
if( p_sys->psz_user && *p_sys->psz_user )
{
net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "Icy-MetaData: 1\r\n" );
- net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "Connection: Close\r\n");
+ if( p_sys->b_continuous && p_sys->i_version == 1 )
+ {
+ net_Printf( VLC_OBJECT( p_access ), p_sys->fd, NULL,
+ "Connection: keep-alive\r\n" );
+ }
+ else
+ {
+ net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL,
+ "Connection: Close\r\n");
+ p_sys->b_continuous = VLC_FALSE;
+ }
if( net_Printf( VLC_OBJECT(p_access), p_sys->fd, NULL, "\r\n" ) < 0 )
{
if( !strcasecmp( psz, "Content-Length" ) )
{
- p_access->info.i_size = i_tell + atoll( p );
- msg_Dbg( p_access, "stream size="I64Fd, p_access->info.i_size );
+ if( p_sys->b_continuous )
+ {
+ p_access->info.i_size = -1;
+ msg_Dbg( p_access, "this frame size="I64Fd, atoll(p ) );
+ p_sys->i_remaining = atoll( p );
+ }
+ else
+ {
+ p_access->info.i_size = i_tell + atoll( p );
+ msg_Dbg( p_access, "stream size="I64Fd, p_access->info.i_size );
+ }
}
else if( !strcasecmp( psz, "Location" ) )
{
else if( !strcasecmp( psz, "Pragma" ) )
{
if( !strcasecmp( psz, "Pragma: features" ) )
- p_sys->b_mms = VLC_TRUE;
+ p_sys->b_mms = VLC_TRUE;
if( p_sys->psz_pragma ) free( p_sys->psz_pragma );
p_sys->psz_pragma = strdup( p );
msg_Dbg( p_access, "Pragma: %s", p_sys->psz_pragma );
if( !strncasecmp( p, "Icecast", 7 ) ||
!strncasecmp( p, "Nanocaster", 10 ) )
{
- /* Remember if this is Icecast
- * we need to force mp3 in some cases without breaking autodetection */
+ /* Remember if this is Icecast
+ * we need to force mp3 in some cases without breaking
+ * autodetection */
- /* Let live365 streams (nanocaster) piggyback on the icecast routine.
- * They look very similar */
+ /* Let live 65 streams (nanocaster) piggyback on the icecast
+ * routine. They look very similar */
p_sys->b_reconnect = VLC_TRUE;
p_sys->b_pace_control = VLC_FALSE;
#include "xtag.h"
-#undef CMML_DEBUG
+#undef CMML_DEBUG
/*****************************************************************************
* decoder_sys_t : decoder descriptor
/*****************************************************************************
* Local prototypes
*****************************************************************************/
-static int OpenDecoder ( vlc_object_t * );
-static void CloseDecoder ( vlc_object_t * );
+static int OpenDecoder ( vlc_object_t * );
+static void CloseDecoder ( vlc_object_t * );
-static void DecodeBlock ( decoder_t *, block_t ** );
+static subpicture_t *DecodeBlock ( decoder_t *, block_t ** );
-static void ParseText ( decoder_t *, block_t * );
+static void ParseText ( decoder_t *, block_t * );
/*****************************************************************************
* Exported prototypes
****************************************************************************
* This function must be fed with complete subtitles units.
****************************************************************************/
-static void DecodeBlock( decoder_t *p_dec, block_t **pp_block )
+static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
+ subpicture_t *p_spu;
+
if( !pp_block || *pp_block == NULL )
{
- return;
+ return NULL;
}
ParseText( p_dec, *pp_block );
block_Release( *pp_block );
*pp_block = NULL;
+
+ /* allocate an empty subpicture to return. the actual subpicture
+ * displaying is done in the DisplayAnchor function in intf.c (called from
+ * DisplayPendingAnchor, which in turn is called from the main RunIntf
+ * loop). */
+ p_spu = p_dec->pf_spu_buffer_new( p_dec );
+ if( !p_spu )
+ {
+ msg_Dbg( p_dec, "couldn't allocate new subpicture" );
+ return NULL;
+ }
+
+ return p_spu;
}
/*****************************************************************************
#undef CMML_INTF_USE_TIMED_URIS
#undef CMML_INTF_DEBUG
-#undef CMML_INTF_SUBPICTURE_DEBUG
#undef CMML_INTF_HISTORY_DEBUG
/*****************************************************************************
msg_Dbg( p_intf, "freeing CMML interface" );
#endif
- /* Erase the anchor text description from the video output if it exists */
+ /* erase the anchor text description from the video output if it exists */
p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
if( p_vout )
{
+ /* enable CMML as a subtitle track */
spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, DEFAULT_CHAN );
vlc_object_release( p_vout );
}
var_DelCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf );
vlc_object_release( p_intf->p_sys->p_cmml_decoder );
-
+
free( p_intf->p_sys );
}
history_t *p_history = NULL;
history_item_t *p_history_item = NULL;
char *psz_timed_url;
-
+
p_history = GetHistory( p_playlist );
/* create history item */
if( psz_anchor_url )
{
- /* Should display subtitle underlined and in blue,
- * but it looks like VLC doesn't implement any
- * text styles yet. D'oh! */
+ /* Should display subtitle underlined and in blue, but it looks
+ * like VLC doesn't implement any text styles yet. D'oh! */
p_style = &blue_with_underline;
}
i_margin_h, i_margin_v, i_now, 0 ) == VLC_SUCCESS )
{
/* Displayed successfully */
-#ifdef CMML_INTF_SUBPICTURE_DEBUG
- msg_Dbg( p_intf, "subpicture created at (%d, %d) (%d, %d)",
- p_subpicture->i_x, p_subpicture->i_y,
- p_subpicture->i_width, p_subpicture->i_height );
-#endif
}
else
{
return NULL;
}
- i_ret = speex_decode( p_sys->p_state, &p_sys->bits,
- (int16_t *)p_aout_buffer->p_buffer );
+ i_ret = speex_decode_int( p_sys->p_state, &p_sys->bits,
+ (int16_t *)p_aout_buffer->p_buffer );
if( i_ret == -1 )
{
/* End of stream */
}
if( p_sys->p_header->nb_channels == 2 )
- speex_decode_stereo( (int16_t *)p_aout_buffer->p_buffer,
- p_sys->p_header->frame_size, &p_sys->stereo );
+ speex_decode_stereo_int( (int16_t *)p_aout_buffer->p_buffer,
+ p_sys->p_header->frame_size,
+ &p_sys->stereo );
/* Date management */
p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
/* Encode current frame */
if( p_enc->fmt_in.audio.i_channels == 2 )
- speex_encode_stereo( p_samples, p_sys->i_frame_length,
- &p_sys->bits );
+ speex_encode_stereo_int( p_samples, p_sys->i_frame_length,
+ &p_sys->bits );
#if 0
if( p_sys->preprocess )
speex_preprocess( p_sys->preprocess, p_samples, NULL );
#endif
- speex_encode( p_sys->p_state, p_samples, &p_sys->bits );
+ speex_encode_int( p_sys->p_state, p_samples, &p_sys->bits );
p_buffer += p_sys->i_frame_size;
p_sys->i_samples_delay -= p_sys->i_frame_length;
vlc_bool_t b_still;
mtime_t i_still_end;
+ mtime_t i_still_length;
mtime_t i_time;
mtime_t i_frame_length;
};
/*****************************************************************************
- * Peek: Helper function to peek data with incremental size.
+ * Peek: Helper function to peek data with incremental size.
* \return VLC_FALSE if peek no more data, VLC_TRUE otherwise.
*****************************************************************************/
static vlc_bool_t Peek( demux_t *p_demux, vlc_bool_t b_first )
if( p_sys->b_still )
{
- p_sys->i_still_end = mdate() + I64C(5000000);
+ p_sys->i_still_end = mdate() + p_sys->i_still_length;
}
return 1;
goto error;
}
+
+ var_Create( p_demux, "mjpeg-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
+ var_Get( p_demux, "mjpeg-fps", &val );
+ p_sys->i_frame_length = 0;
+
/* Check for jpeg file extension */
p_sys->b_still = VLC_FALSE;
p_sys->i_still_end = 0;
!strcasecmp( psz_ext, ".jpg" ) ) )
{
p_sys->b_still = VLC_TRUE;
+ if( val.f_float)
+ {
+ p_sys->i_still_length =1000000.0 / val.f_float;
+ }
+ else
+ {
+ /* Defaults to 1fps */
+ p_sys->i_still_length = 1000000;
+ }
}
-
- var_Create( p_demux, "mjpeg-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
- var_Get( p_demux, "mjpeg-fps", &val );
- p_sys->i_frame_length = 0;
- if( val.f_float )
+ else if ( val.f_float )
{
p_sys->i_frame_length = 1000000.0 / val.f_float;
}
}
else if( p_sys->b_still && p_sys->i_still_end )
{
- msleep( 40000 );
+ msleep( 400 );
return 1;
}
p_stream->b_force_backup = 1;
}
+ else if( !strncmp(content_type_string, "audio/x-speex", 14) )
+ {
+ p_stream->fmt.i_cat = AUDIO_ES;
+ p_stream->fmt.i_codec = VLC_FOURCC( 's','p','x',' ' );
+
+ p_stream->b_force_backup = 1;
+ }
else if( !strncmp(content_type_string, "video/x-theora", 14) )
{
p_stream->fmt.i_cat = VIDEO_ES;
/// Class to handle a video output window
-class VoutWindow: public GenericWindow
+class VoutWindow: private GenericWindow
{
public:
VoutWindow( intf_thread_t *pIntf, int xPos, int yPos,
bool dragDrop, bool playOnDrop, GenericWindow &rParent );
virtual ~VoutWindow();
- /// These methods are redefined here to make them public
+ /// Make some functions public
//@{
- /// Show the window
- virtual void show() { GenericWindow::show(); }
-
- /// Hide the window
- virtual void hide() { GenericWindow::hide(); }
-
- /// Move the window
- virtual void move( int left, int top )
- { GenericWindow::move( left, top ); }
+ using GenericWindow::show;
+ using GenericWindow::hide;
+ using GenericWindow::move;
//@}
/// Resize the window
p_item->input.psz_uri = strdup( uri_text->GetLineText(0).mb_str() );
playlist_ItemAddInfo( p_item,"General","Author",
author_text->GetLineText(0).mb_str() );
- vlc_bool_t b_old_enabled = p_item->b_enabled;
-
- playlist_t * p_playlist =
- (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
- FIND_ANYWHERE );
- if( p_playlist != NULL )
- {
- if( b_old_enabled == VLC_FALSE && enabled_checkbox->IsChecked() )
- p_playlist->i_enabled ++;
- else if( b_old_enabled == VLC_TRUE && !enabled_checkbox->IsChecked() )
- p_playlist->i_enabled --;
-
- vlc_object_release( p_playlist );
- }
-
- p_item->b_enabled = enabled_checkbox->IsChecked() ? VLC_TRUE : VLC_FALSE ;
vlc_mutex_unlock( &p_item->input.lock );
EndModal( wxID_OK );
}
SortTitle_Event,
RSortTitle_Event,
- SortAuthor_Event,
- RSortAuthor_Event,
Randomize_Event,
EnableSelection_Event,
Repeat_Event,
SelectAll_Event,
- Up_Event,
- Down_Event,
- Infos_Event,
-
PopupPlay_Event,
PopupPlayThis_Event,
PopupSort_Event,
EVT_MENU(SortTitle_Event, Playlist::OnSort)
EVT_MENU(RSortTitle_Event, Playlist::OnSort)
- EVT_MENU(SortAuthor_Event, Playlist::OnSort)
- EVT_MENU(RSortAuthor_Event, Playlist::OnSort)
EVT_MENU(Randomize_Event, Playlist::OnSort)
EVT_MENU(InvertSelection_Event, Playlist::OnInvertSelection)
EVT_MENU(DeleteSelection_Event, Playlist::OnDeleteSelection)
EVT_MENU(SelectAll_Event, Playlist::OnSelectAll)
- EVT_MENU(Infos_Event, Playlist::OnInfos)
EVT_MENU_OPEN( Playlist::OnMenuOpen )
EVT_MENU( -1, Playlist::OnMenuEvent )
/* Button events */
EVT_BUTTON( Search_Event, Playlist::OnSearch)
EVT_BUTTON( Save_Event, Playlist::OnSave)
- EVT_BUTTON( Infos_Event, Playlist::OnInfos)
-
- EVT_BUTTON( Up_Event, Playlist::OnUp)
- EVT_BUTTON( Down_Event, Playlist::OnDown)
EVT_TEXT(SearchText_Event, Playlist::OnSearchTextChange)
p_sd_menu = SDMenu();
i_current_view = VIEW_SIMPLE;
+ b_changed_view = VLC_FALSE;
i_title_sorted = 0;
- i_author_sorted = 0;
i_group_sorted = 0;
i_duration_sorted = 0;
sort_menu->Append( SortTitle_Event, wxU(_("Sort by &title")) );
sort_menu->Append( RSortTitle_Event, wxU(_("&Reverse sort by title")) );
sort_menu->AppendSeparator();
- sort_menu->Append( SortAuthor_Event, wxU(_("Sort by &author")) );
- sort_menu->Append( RSortAuthor_Event, wxU(_("Reverse sort by author")) );
- sort_menu->AppendSeparator();
sort_menu->Append( Randomize_Event, wxU(_("&Shuffle Playlist")) );
/* Create our "Selection" menu */
Rebuild();
}
-void Playlist::OnSize( wxSizeEvent& event)
-{
- event.Skip();
-}
-
Playlist::~Playlist()
{
playlist_t *p_playlist =
}
/**********************************************************************
- * Update one playlist item
+ * Update functions
**********************************************************************/
+
+/* Update a node */
void Playlist::UpdateNode( playlist_t *p_playlist, playlist_item_t *p_node,
wxTreeItemId node )
{
}
}
+
/* Creates the node p_node as last child of parent */
void Playlist::CreateNode( playlist_t *p_playlist, playlist_item_t *p_node,
wxTreeItemId parent )
UpdateNodeChildren( p_playlist, p_node, node );
}
+/* Update all children (recursively) of this node */
void Playlist::UpdateNodeChildren( playlist_t *p_playlist,
playlist_item_t *p_node,
wxTreeItemId node )
}
}
-wxTreeItemId Playlist::FindItem( wxTreeItemId root, playlist_item_t *p_item )
+/* Set current item */
+void Playlist::SetCurrentItem( wxTreeItemId item )
{
- long cookie;
- PlaylistItem *p_wxcurrent;
- wxTreeItemId search;
- wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
- wxTreeItemId child;
-
- p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( root );
-
- if( p_wxcurrent->p_item == p_item )
+ if( item.IsOk() )
{
- return root;
+ treectrl->SetItemBold( item, true );
+ treectrl->EnsureVisible( item );
}
+}
+
+/* Update an item in the tree */
+void Playlist::UpdateTreeItem( playlist_t *p_playlist, wxTreeItemId item )
+{
+ playlist_item_t *p_item =
+ ((PlaylistItem *)treectrl->GetItemData( item ))->p_item;
if( !p_item )
{
- wxTreeItemId dummy;
- return dummy;
+ return;
}
- while( item.IsOk() )
- {
- p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item );
- if( p_wxcurrent->p_item == p_item )
- {
- return item;
- }
- if( treectrl->ItemHasChildren( item ) )
- {
- wxTreeItemId search = FindItem( item, p_item );
- if( search.IsOk() )
- {
- return search;
- }
- }
- item = treectrl->GetNextChild( root, cookie);
- }
- /* Not found */
- wxTreeItemId dummy;
- return dummy;
-}
+ wxString msg;
+ char *psz_author = playlist_ItemGetInfo( p_item, _("Meta-information"),
+ _("Artist"));
+ char psz_duration[MSTRTIME_MAX_SIZE];
+ mtime_t dur = p_item->input.i_duration;
-wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string, wxTreeItemId current, vlc_bool_t *pb_current_found )
-{
- long cookie;
- PlaylistItem *p_wxcurrent;
- wxTreeItemId search;
- wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
- wxTreeItemId child;
+ if( dur != -1 )
+ secstotimestr( psz_duration, dur/1000000 );
+ else
+ memcpy( psz_duration, "-:--:--", sizeof("-:--:--") );
- while( item.IsOk() )
+ if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE )
{
- if( treectrl->GetItemText( item).Lower().Contains(
- search_string.Lower() ) )
- {
- if( !current.IsOk() || *pb_current_found == VLC_TRUE )
- {
- return item;
- }
- else if( current.IsOk() && item == current )
- {
- *pb_current_found = VLC_TRUE;
- }
- }
- if( treectrl->ItemHasChildren( item ) )
- {
- wxTreeItemId search = FindItemByName( item, search_string, current,
- pb_current_found );
- if( search.IsOk() )
- {
- return search;
- }
- }
- item = treectrl->GetNextChild( root, cookie);
+ msg.Printf( wxString( wxL2U( p_item->input.psz_name ) ) + wxU( " ( ") +
+ wxString(wxL2U(psz_duration ) ) + wxU( ")") );
}
- /* Not found */
- wxTreeItemId dummy;
- return dummy;
-}
-
+ else
+ {
+ msg.Printf( wxString(wxU( psz_author )) + wxT(" - ") +
+ wxString(wxL2U(p_item->input.psz_name)) + wxU( " ( ") +
+ wxString(wxL2U(psz_duration ) ) + wxU( ")") );
+ }
+ treectrl->SetItemText( item , msg );
-void Playlist::SetCurrentItem( wxTreeItemId item )
-{
- if( item.IsOk() )
+ if( p_playlist->status.p_item == p_item )
{
- treectrl->SetItemBold( item, true );
- treectrl->EnsureVisible( item );
+ SetCurrentItem( item );
+ }
+ else
+ {
+ treectrl->SetItemBold( item, false );
}
}
+/* Process a AppendItem request */
void Playlist::AppendItem( wxCommandEvent& event )
{
playlist_add_t *p_add = (playlist_add_t *)event.GetClientData();
playlist_t *p_playlist =
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
+ wxTreeItemId item,node;
if( p_playlist == NULL )
{
event.Skip();
if( p_add->i_view != i_current_view )
{
- vlc_object_release( p_playlist );
- event.Skip();
- return;
+ goto update;
}
- wxTreeItemId node = FindItem( treectrl->GetRootItem(), p_add->p_node );
+ node = FindItem( treectrl->GetRootItem(), p_add->p_node );
if( !node.IsOk() )
{
- vlc_object_release( p_playlist );
- event.Skip();
- return;
+ goto update;
}
- wxTreeItemId item = treectrl->AppendItem( node,
- wxL2U( p_add->p_item->input.psz_name ), -1,-1,
- new PlaylistItem( p_add->p_item ) );
+ item = treectrl->AppendItem( node,
+ wxL2U( p_add->p_item->input.psz_name ), -1,-1,
+ new PlaylistItem( p_add->p_item ) );
treectrl->SetItemImage( item, p_add->p_item->input.i_type );
if( item.IsOk() && p_add->p_item->i_children == -1 )
UpdateTreeItem( p_playlist, item );
}
- statusbar->SetStatusText( wxString::Format( wxU(_(
- "%i items in playlist")),
- p_playlist->i_size ), 0 );
+update:
+ int i_count = CountItems( treectrl->GetRootItem());
+ if( i_count != p_playlist->i_size )
+ {
+ statusbar->SetStatusText( wxString::Format( wxU(_(
+ "%i items in playlist (%i not shown)")),
+ p_playlist->i_size,
+ p_playlist->i_size - i_count ) );
+ if( !b_changed_view )
+ {
+ i_current_view = VIEW_CATEGORY;
+ b_changed_view = VLC_TRUE;
+ b_need_update = VLC_TRUE;
+ }
+ }
+ else
+ {
+ statusbar->SetStatusText( wxString::Format( wxU(_(
+ "%i items in playlist")),
+ p_playlist->i_size ), 0 );
+ }
vlc_object_release( p_playlist );
+ return;
}
+/* Process a updateitem request */
void Playlist::UpdateItem( int i )
{
if( i < 0 ) return; /* Sanity check */
vlc_object_release(p_playlist);
}
-void Playlist::UpdateTreeItem( playlist_t *p_playlist, wxTreeItemId item )
-{
- playlist_item_t *p_item =
- ((PlaylistItem *)treectrl->GetItemData( item ))->p_item;
- if( !p_item )
- {
- return;
- }
- wxString msg;
- char *psz_author = playlist_ItemGetInfo( p_item, _("Meta-information"),
- _("Artist"));
- char psz_duration[MSTRTIME_MAX_SIZE];
- mtime_t dur = p_item->input.i_duration;
+/**********************************************************************
+ * Search functions (internal
+ **********************************************************************/
- if( dur != -1 )
- secstotimestr( psz_duration, dur/1000000 );
- else
- memcpy( psz_duration, "-:--:--", sizeof("-:--:--") );
+/* Find a wxItem from a playlist_item */
+wxTreeItemId Playlist::FindItem( wxTreeItemId root, playlist_item_t *p_item )
+{
+ long cookie;
+ PlaylistItem *p_wxcurrent;
+ wxTreeItemId search;
+ wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
+ wxTreeItemId child;
- if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE )
+ p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( root );
+
+ if( p_wxcurrent->p_item == p_item )
{
- msg.Printf( wxString( wxL2U( p_item->input.psz_name ) ) + wxU( " ( ") +
- wxString(wxL2U(psz_duration ) ) + wxU( ")") );
+ return root;
}
- else
+
+ if( !p_item )
{
- msg.Printf( wxString(wxU( psz_author )) + wxT(" - ") +
- wxString(wxL2U(p_item->input.psz_name)) + wxU( " ( ") +
- wxString(wxL2U(psz_duration ) ) + wxU( ")") );
+ wxTreeItemId dummy;
+ return dummy;
}
- treectrl->SetItemText( item , msg );
- if( p_playlist->status.p_item == p_item )
+ while( item.IsOk() )
{
- SetCurrentItem( item );
+ p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item );
+ if( p_wxcurrent->p_item == p_item )
+ {
+ return item;
+ }
+ if( treectrl->ItemHasChildren( item ) )
+ {
+ wxTreeItemId search = FindItem( item, p_item );
+ if( search.IsOk() )
+ {
+ return search;
+ }
+ }
+ item = treectrl->GetNextChild( root, cookie );
}
- else
+ /* Not found */
+ wxTreeItemId dummy;
+ return dummy;
+}
+
+int Playlist::CountItems( wxTreeItemId root )
+{
+ long cookie;
+ int count = 0;
+ wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
+
+ while( item.IsOk() )
{
- treectrl->SetItemBold( item, false );
+ if( treectrl->ItemHasChildren( item ) )
+ {
+ count += CountItems( item );
+ }
+ else if( ( (PlaylistItem *)treectrl->GetItemData( item ) )->
+ p_item->i_children == -1 )
+ count++;
+ item = treectrl->GetNextChild( root, cookie );
}
-#if 0
- if( p_item->b_enabled == VLC_FALSE )
+ return count;
+}
+
+/* Find a wxItem from a name (from current) */
+wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string, wxTreeItemId current, vlc_bool_t *pb_current_found )
+{
+ long cookie;
+ wxTreeItemId search;
+ wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
+ wxTreeItemId child;
+
+ while( item.IsOk() )
{
- wxListItem listitem;
- listitem.m_itemId = i;
- listitem.SetTextColour( *wxLIGHT_GREY);
- listview->SetItem(listitem);
+ if( treectrl->GetItemText( item).Lower().Contains(
+ search_string.Lower() ) )
+ {
+ if( !current.IsOk() || *pb_current_found == VLC_TRUE )
+ {
+ return item;
+ }
+ else if( current.IsOk() && item == current )
+ {
+ *pb_current_found = VLC_TRUE;
+ }
+ }
+ if( treectrl->ItemHasChildren( item ) )
+ {
+ wxTreeItemId search = FindItemByName( item, search_string, current,
+ pb_current_found );
+ if( search.IsOk() )
+ {
+ return search;
+ }
+ }
+ item = treectrl->GetNextChild( root, cookie);
}
-#endif
+ /* Not found */
+ wxTreeItemId dummy;
+ return dummy;
}
/**********************************************************************
{
return;
}
+ int i_count = CountItems( treectrl->GetRootItem()) ;
+
+ if( i_count > p_playlist->i_size && !b_changed_view )
+ {
+ i_current_view = VIEW_CATEGORY;
+ b_changed_view = VLC_TRUE;
+ }
/* ...and rebuild it */
vlc_mutex_lock( &p_playlist->object_lock );
item = root;
}
- SetCurrentItem( item );
-
-/* GetChildrenCount does count internal nodes :(
- if( treectrl->GetChildrenCount( root, true ) !=
- p_playlist->i_size )
+ i_count = CountItems( treectrl->GetRootItem() );
+ if( i_count != p_playlist->i_size )
{
- statusbar->SetStatusText( wxString::Format( wxT(_(
+ statusbar->SetStatusText( wxString::Format( wxU(_(
"%i items in playlist (%i not shown)")),
p_playlist->i_size,
- p_playlist->i_size -
- treectrl->GetChildrenCount( root, true ) ) );
+ p_playlist->i_size - i_count ) );
}
else
{
-*/
statusbar->SetStatusText( wxString::Format( wxU(_(
"%i items in playlist")),
p_playlist->i_size ), 0 );
-// }
+ }
+ SetCurrentItem( item );
vlc_mutex_unlock( &p_playlist->object_lock );
vlc_object_release( p_playlist );
}
+
+
void Playlist::ShowPlaylist( bool show )
{
if( show ) Rebuild();
Show( show );
}
+/* This function is called on a regular basis */
void Playlist::UpdatePlaylist()
{
i_update_counter++;
vlc_object_release( p_playlist );
}
+void Playlist::DeleteNode( playlist_item_t *p_item )
+{
+ playlist_t *p_playlist =
+ (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ playlist_NodeDelete( p_playlist, p_item, VLC_TRUE );
+
+ vlc_object_release( p_playlist );
+}
+
+
void Playlist::OnClose( wxCommandEvent& WXUNUSED(event) )
{
Hide();
}
-/********************************************************************
- * Move functions
- ********************************************************************/
-void Playlist::OnUp( wxCommandEvent& event )
-{
- playlist_t *p_playlist =
- (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
- FIND_ANYWHERE );
- if( p_playlist == NULL )
- {
- return;
- }
-#if 0
- /* We use the first selected item, so find it */
- long i_item = listview->GetNextItem( -1, wxLIST_NEXT_ALL,
- wxLIST_STATE_SELECTED);
- if( i_item > 0 && i_item < p_playlist->i_size )
- {
- playlist_Move( p_playlist, i_item, i_item - 1 );
- listview->Focus( i_item - 1 );
- }
-#endif
- vlc_object_release( p_playlist );
-}
-
-void Playlist::OnDown( wxCommandEvent& event )
-{
- playlist_t *p_playlist =
- (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
- FIND_ANYWHERE );
- if( p_playlist == NULL )
- {
- return;
- }
-#if 0
- /* We use the first selected item, so find it */
- long i_item = listview->GetNextItem( -1, wxLIST_NEXT_ALL,
- wxLIST_STATE_SELECTED );
- if( i_item >= 0 && i_item < p_playlist->i_size - 1 )
- {
- playlist_Move( p_playlist, i_item, i_item + 2 );
- listview->Focus( i_item + 1 );
- }
-#endif
- vlc_object_release( p_playlist );
-}
-
/********************************************************************
* Sorting functions
********************************************************************/
playlist_t *p_playlist =
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
+ PlaylistItem *p_wxitem;
+ p_wxitem = (PlaylistItem *)treectrl->GetItemData( treectrl->GetRootItem() );
+
if( p_playlist == NULL )
{
return;
}
+ vlc_mutex_lock( &p_playlist->object_lock );
switch( event.GetId() )
{
case SortTitle_Event:
- playlist_SortTitle( p_playlist, ORDER_NORMAL );
- break;
+ playlist_RecursiveNodeSort( p_playlist, p_wxitem->p_item,
+ SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
+ break;
case RSortTitle_Event:
- playlist_SortTitle( p_playlist, ORDER_REVERSE );
- break;
- case SortAuthor_Event:
- playlist_SortAuthor(p_playlist, ORDER_NORMAL );
- break;
- case RSortAuthor_Event:
- playlist_SortAuthor( p_playlist, ORDER_REVERSE );
- break;
- case Randomize_Event:
- playlist_Sort( p_playlist, SORT_RANDOM, ORDER_NORMAL );
- break;
+ playlist_RecursiveNodeSort( p_playlist, p_wxitem->p_item,
+ SORT_TITLE_NODES_FIRST, ORDER_REVERSE );
}
- vlc_object_release( p_playlist );
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
Rebuild();
}
/**********************************************************************
- * Search functions
+ * Search functions (user)
**********************************************************************/
void Playlist::OnSearchTextChange( wxCommandEvent& WXUNUSED(event) )
{
}
}
-#if 0
- for( i_current = 0; i_current < listview->GetItemCount(); i_current++ )
- {
- if( listview->GetItemState( i_current, wxLIST_STATE_SELECTED ) ==
- wxLIST_STATE_SELECTED )
- {
- i_first = i_current;
- break;
- }
- }
-
- if( i_first == listview->GetItemCount() )
- {
- i_first = -1;
- }
-
- for( i_current = i_first + 1; i_current < listview->GetItemCount();
- i_current++ )
- {
- wxListItem listitem;
- listitem.SetId( i_current );
- listview->GetItem( listitem );
- if( listitem.m_text.Lower().Contains( search_string.Lower() ) )
- {
- i_item = i_current;
- b_ok = true;
- break;
- }
- listitem.SetColumn( 1 );
- listview->GetItem( listitem );
- if( listitem.m_text.Lower().Contains( search_string.Lower() ) )
- {
- i_item = i_current;
- b_ok = true;
- break;
- }
- }
- if( !b_ok )
- {
- for( i_current = -1 ; i_current < i_first - 1;
- i_current++ )
- {
- wxListItem listitem;
- listitem.SetId( i_current );
- listview->GetItem( listitem );
- if( listitem.m_text.Lower().Contains( search_string.Lower() ) )
- {
- i_item = i_current;
- b_ok = true;
- break;
- }
- listitem.SetColumn( 1 );
- listview->GetItem( listitem );
- if( listitem.m_text.Lower().Contains( search_string.Lower() ) )
- {
- i_item = i_current;
- b_ok = true;
- break;
- }
- }
- }
-
- if( i_item < 0 || i_item >= listview->GetItemCount() )
- {
- return;
- }
-
- for( long item = 0; item < listview->GetItemCount(); item++ )
- {
- listview->Select( item, FALSE );
- }
-
- wxListItem listitem;
- listitem.SetId(i_item);
- listitem.m_state = wxLIST_STATE_SELECTED;
- listview->Select( i_item, TRUE );
- listview->Focus( i_item );
-}
-#endif
-
/**********************************************************************
* Selection functions
**********************************************************************/
{
return;
}
-#if 0
- for( long item = listview->GetItemCount() - 1; item >= 0; item-- )
- {
- if( listview->IsSelected( item ) )
- {
- /*XXX*/
- playlist_Enable( p_playlist, item );
- UpdateItem( item );
- }
- }
-#endif
+ msg_Warn( p_playlist, "not implemented");
vlc_object_release( p_playlist);
}
{
return;
}
-#if 0
- for( long item = listview->GetItemCount() - 1; item >= 0; item-- )
- {
- if( listview->IsSelected( item ) )
- {
- /*XXX*/
- playlist_Disable( p_playlist, item );
- UpdateItem( item );
- }
- }
-#endif
+
+ msg_Warn( p_playlist, "not implemented");
+
vlc_object_release( p_playlist);
}
vlc_object_release( p_playlist );
}
+/********************************************************************
+ * Event
+ ********************************************************************/
void Playlist::OnActivateItem( wxTreeEvent& event )
{
playlist_item_t *p_item,*p_node;
}
}
-void Playlist::ShowInfos( int i_item )
-{
-}
-
-void Playlist::OnInfos( wxCommandEvent& WXUNUSED(event) )
-{
-}
-
void Playlist::OnEnDis( wxCommandEvent& event )
{
playlist_t *p_playlist =
{
return;
}
+ msg_Warn( p_intf, "not implemented" );
vlc_object_release( p_playlist );
}
if( p_view != NULL )
{
+ b_changed_view = VLC_TRUE;
i_current_view = i_new_view;
playlist_ViewUpdate( p_playlist, i_new_view );
Rebuild();
else if( i_new_view >= VIEW_FIRST_SORTED &&
i_new_view <= VIEW_LAST_SORTED )
{
+ b_changed_view = VLC_TRUE;
playlist_ViewInsert( p_playlist, i_new_view, "View" );
playlist_ViewUpdate( p_playlist, i_new_view );
{
return NULL;
}
- vlc_value_t val, val_list, text_list;
p_sd_menu = new wxMenu;
vlc_list_t *p_list = vlc_list_find( p_playlist, VLC_OBJECT_MODULE,
}
else
{
- //DeleteNode( p_wxitem->p_item );
+ DeleteNode( p_wxitem->p_item );
}
}
private:
void DeleteItem( int item );
- void ShowInfos( int item );
+ void DeleteNode( playlist_item_t *node );
/* Event handlers (these functions should _not_ be virtual) */
- void OnSize( wxSizeEvent &event );
-
/* Menu Handlers */
void OnAddFile( wxCommandEvent& event );
void OnAddDir( wxCommandEvent& event );
void OnAddMRL( wxCommandEvent& event );
void OnClose( wxCommandEvent& event );
- void OnSearch( wxCommandEvent& event );
- void OnEnDis( wxCommandEvent& event );
- void OnInfos( wxCommandEvent& event );
- void OnSearchTextChange( wxCommandEvent& event );
+
+ void OnEnableSelection( wxCommandEvent& event );
+ void OnDisableSelection( wxCommandEvent& event );
+ void OnInvertSelection( wxCommandEvent& event );
+ void OnDeleteSelection( wxCommandEvent& event );
+ void OnSelectAll( wxCommandEvent& event );
+
void OnOpen( wxCommandEvent& event );
void OnSave( wxCommandEvent& event );
+ /* Search (user) */
+ void OnSearch( wxCommandEvent& event );
+ void OnSearchTextChange( wxCommandEvent& event );
+ wxTextCtrl *search_text;
+ wxButton *search_button;
+ wxTreeItemId search_current;
+
+ void OnEnDis( wxCommandEvent& event );
+
+ /* Sort */
+ int i_sort_mode;
void OnSort( wxCommandEvent& event );
+ int i_title_sorted;
+ int i_group_sorted;
+ int i_duration_sorted;
+ /* Dynamic menus */
void OnMenuEvent( wxCommandEvent& event );
void OnMenuOpen( wxMenuEvent& event );
-
+ wxMenu *p_view_menu;
+ wxMenu *p_sd_menu;
wxMenu *ViewMenu();
wxMenu *SDMenu();
void OnUp( wxCommandEvent& event);
void OnDown( wxCommandEvent& event);
- void OnEnableSelection( wxCommandEvent& event );
- void OnDisableSelection( wxCommandEvent& event );
- void OnInvertSelection( wxCommandEvent& event );
- void OnDeleteSelection( wxCommandEvent& event );
- void OnSelectAll( wxCommandEvent& event );
void OnRandom( wxCommandEvent& event );
void OnRepeat( wxCommandEvent& event );
void OnLoop ( wxCommandEvent& event );
void OnKeyDown( wxTreeEvent& event );
void OnNewGroup( wxCommandEvent& event );
- /* Popup functions */
+ /* Popup */
+ wxMenu *popup_menu;
+ wxTreeItemId i_popup_item;
+ playlist_item_t *p_popup_item;
+ playlist_item_t *p_popup_parent;
void OnPopup( wxContextMenuEvent& event );
void OnPopupPlay( wxMenuEvent& event );
void OnPopupSort( wxMenuEvent& event );
void UpdateNode( playlist_t *, playlist_item_t*, wxTreeItemId );
void UpdateNodeChildren( playlist_t *, playlist_item_t*, wxTreeItemId );
void CreateNode( playlist_t *, playlist_item_t*, wxTreeItemId );
+ void UpdateTreeItem( playlist_t *, wxTreeItemId );
+ void SetCurrentItem( wxTreeItemId );
+ /* Search (internal) */
+ int CountItems( wxTreeItemId);
wxTreeItemId FindItem( wxTreeItemId, playlist_item_t * );
- wxTreeItemId FindItemByName( wxTreeItemId, wxString, wxTreeItemId, vlc_bool_t *);
- void SetCurrentItem( wxTreeItemId );
- void UpdateTreeItem( playlist_t *, wxTreeItemId );
+ wxTreeItemId FindItemByName( wxTreeItemId, wxString,
+ wxTreeItemId, vlc_bool_t *);
/* Custom events */
void OnPlaylistEvent( wxCommandEvent& event );
- wxTextCtrl *search_text;
- wxButton *search_button;
DECLARE_EVENT_TABLE();
- wxMenu *popup_menu;
-
- wxMenu *p_view_menu;
- wxMenu *p_sd_menu;
-
- char **pp_sds;
+ /* Global widgets */
wxStatusBar *statusbar;
-
ItemInfoDialog *iteminfo_dialog;
- intf_thread_t *p_intf;
- wxTreeCtrl *treectrl;
int i_update_counter;
- int i_sort_mode;
+ intf_thread_t *p_intf;
+ wxTreeCtrl *treectrl;
int i_current_view;
+ vlc_bool_t b_changed_view;
+ char **pp_sds;
- wxTreeItemId i_popup_item;
- wxTreeItemId search_current;
- playlist_item_t *p_popup_item;
- playlist_item_t *p_popup_parent;
- int i_title_sorted;
- int i_author_sorted;
- int i_group_sorted;
- int i_duration_sorted;
};
/* ItemInfo Dialog */
wxTreeCtrl *info_tree;
wxTreeItemId info_root;
- wxCheckBox *enabled_checkbox;
};
}
/* Decide whether we should add a playlist item for this SDP */
+ /* Parse connection information (c= & m= ) */
+ if( ParseConnection( VLC_OBJECT(p_sd), p_sdp ) )
+ {
+ p_sdp->psz_uri = NULL;
+ }
/* Multi-media or no-parse -> pass to LIVE.COM */
- if( p_sdp->i_media > 1 || p_sd->p_sys->b_parse == VLC_FALSE )
+ if( p_sdp->i_media > 1 || ( p_sdp->i_media_type != 14 &&
+ p_sdp->i_media_type != 32 &&
+ p_sdp->i_media_type != 33) ||
+ p_sd->p_sys->b_parse == VLC_FALSE )
{
+ if( p_sdp->psz_uri ) free( p_sdp->psz_uri );
asprintf( &p_sdp->psz_uri, "sdp://%s", p_sdp->psz_sdp );
}
- else
- {
- /* Parse connection information (c= & m= ) */
- if( ParseConnection( VLC_OBJECT(p_sd), p_sdp ) )
- {
- p_sdp->psz_uri = NULL;
- }
- }
if( p_sdp->psz_uri == NULL ) return VLC_EGENERIC;