]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/dialogs/vlm/vlm_panel.cpp
all: reworked gui layout of dialog boxes to get rid of the dark gray background colou...
[vlc] / modules / gui / wxwidgets / dialogs / vlm / vlm_panel.cpp
1 /*****************************************************************************
2  * vlm_panel.cpp: VLM Panel
3  *****************************************************************************
4  * Copyright (C) 2000-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/OR MODIFy
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "dialogs/vlm/vlm_panel.hpp"
25 #include "dialogs/vlm/vlm_wrapper.hpp"
26 #include "dialogs/vlm/vlm_stream.hpp"
27 #include "dialogs/vlm/vlm_streampanel.hpp"
28 #include <wx/statline.h>
29
30 #include "charset.h"
31
32 enum
33 {
34     Notebook_Event,
35     Timer_Event,
36     Close_Event,
37     Load_Event,
38     Save_Event,
39 };
40
41 BEGIN_EVENT_TABLE( VLMPanel, wxPanel)
42    EVT_TIMER( Timer_Event, VLMPanel::OnTimer )
43    EVT_BUTTON( wxID_CLOSE, VLMPanel::OnClose )
44    EVT_BUTTON( Load_Event, VLMPanel::OnLoad )
45    EVT_BUTTON( wxID_SAVE, VLMPanel::OnSave )
46 END_EVENT_TABLE()
47
48
49 VLMPanel::VLMPanel( intf_thread_t *_p_intf, wxWindow *_p_parent ) :
50         wxPanel( _p_parent, -1, wxDefaultPosition, wxDefaultSize ),
51        timer( this, Timer_Event )
52 {
53     p_intf = _p_intf;
54     p_parent = _p_parent;
55
56     p_vlm = new VLMWrapper( p_intf );
57     p_vlm->AttachVLM();
58
59     SetAutoLayout( TRUE );
60
61     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
62
63     p_notebook = new wxNotebook( this, Notebook_Event );
64 #if (!wxCHECK_VERSION(2,5,0))
65     wxNotebookSizer *notebook_sizer = new wxNotebookSizer( p_notebook );
66 #endif
67     p_notebook->AddPage( BroadcastPanel( p_notebook ), wxU( _("Broadcasts") ) );
68 #if 0
69     p_notebook->AddPage( VODPanel( p_notebook ), wxU( _("VOD") ) );
70 #endif
71 #if (!wxCHECK_VERSION(2,5,0))
72     panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
73 #else
74     panel_sizer->Add( p_notebook, 1 , wxEXPAND | wxALL, 5 );
75 #endif
76
77     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
78     button_sizer->Add( new wxButton( this, wxID_CLOSE ));
79     button_sizer->Add( 0, 0, 1 );
80     button_sizer->Add( new wxButton( this, Load_Event, wxU(_("Load") ) ), 0, wxRIGHT, 10 );
81     button_sizer->Add( new wxButton( this, wxID_SAVE ));
82     panel_sizer->Add( button_sizer, 0 , wxEXPAND | wxALL, 5 );
83
84     panel_sizer->Layout();
85     SetSizerAndFit( panel_sizer );
86
87     Update();
88
89     timer.Start( 300 );
90 }
91
92 VLMPanel::~VLMPanel()
93 {
94     delete p_vlm;
95 }
96
97 void VLMPanel::OnTimer( wxTimerEvent& event )
98 {
99     Update();
100 }
101
102 void VLMPanel::Update()
103 {
104     unsigned int i;
105     for( i = 0 ; i < broadcasts.size(); i++ )
106     {
107         ((VLMBroadcastStreamPanel *)broadcasts[i])->b_found = VLC_FALSE;
108     }
109     for( i = 0 ; i < vods.size(); i++ )
110     {
111         ((VLMVODStreamPanel *)vods[i])->b_found = VLC_FALSE;
112     }
113
114     p_vlm->LockVLM();
115     /* Iterate over the media, to find the panels to add / remove */
116     /* FIXME: This code should be better wrapped */
117     for( i = 0; i < p_vlm->NbMedia(); i++ )
118     {
119         vlm_media_t *p_media = p_vlm->GetMedia( i );
120
121         if( p_media->i_type == BROADCAST_TYPE )
122         {
123             vlc_bool_t b_foundthis = VLC_FALSE;
124             for( unsigned int j = 0 ; j < broadcasts.size(); j++ )
125             {
126                 VLMBroadcastStreamPanel *p_streamp =
127                        (VLMBroadcastStreamPanel *)(broadcasts[j]);
128                 /* FIXME: dangerous .. */
129                 if( p_streamp->GetStream()->p_media ==  p_media )
130                 {
131                     p_streamp->b_found = VLC_TRUE;
132                     b_foundthis = VLC_TRUE;
133                     break;
134                 }
135             }
136             /* Create the stream */
137             if( !b_foundthis )
138             {
139                 VLMBroadcastStream *p_broadcast =
140                         new VLMBroadcastStream( p_intf, p_media, p_vlm );
141                 AppendBroadcast( p_broadcast );
142             }
143         }
144         else if( p_media->i_type == VOD_TYPE )
145         {
146             vlc_bool_t b_foundthis = VLC_FALSE;
147             for( unsigned int j = 0 ; i < vods.size(); i++ )
148             {
149                 VLMVODStreamPanel *p_streamp = (VLMVODStreamPanel *)( vods[j] );
150                 if(  p_streamp->GetStream()->p_media ==  p_media )
151                 {
152                     p_streamp->b_found = VLC_TRUE;
153                     b_foundthis = VLC_TRUE;
154                     break;
155                 }
156             }
157             /* Create it */
158             if( !b_foundthis )
159             {
160                 VLMVODStream *p_vod = new VLMVODStream(p_intf, p_media, p_vlm );
161                 AppendVOD( p_vod );
162             }
163         }
164     }
165
166     /* Those not marked as found must be removed */
167     vector<VLMBroadcastStreamPanel *>::iterator it = broadcasts.begin();
168     while( it < broadcasts.end() )
169     {
170         if( (*it)->b_found == VLC_FALSE )
171         {
172             vector<VLMBroadcastStreamPanel *>::iterator rem = it;
173             it++;
174             VLMBroadcastStreamPanel *p_remove = *rem;
175             broadcasts.erase( rem );
176             RemoveBroadcast( p_remove );
177             delete p_remove;
178         }
179         else
180             it++;
181     }
182     vector<VLMVODStreamPanel *>::iterator it2 = vods.begin();
183     while( it2 < vods.end() )
184     {
185         if( (*it2)->b_found == VLC_FALSE )
186         {
187             vector<VLMVODStreamPanel *>::iterator rem = it2;
188             it2++;
189             VLMVODStreamPanel *p_remove = *rem;
190             vods.erase( rem );
191             RemoveVOD( p_remove );
192             delete p_remove;
193         }
194         else
195             it2++;
196     }
197
198     /* Update sliders*/
199     for( unsigned int j = 0 ; j < broadcasts.size(); j++ )
200     {
201         VLMBroadcastStreamPanel *p_streamp =
202                 (VLMBroadcastStreamPanel *)( broadcasts[j] );
203         p_streamp->Update();
204     }
205     p_vlm->UnlockVLM();
206 }
207
208 void VLMPanel::OnClose( wxCommandEvent &event )
209 {
210     ((VLMFrame*)p_parent)->OnClose( *( new wxCloseEvent() ) );
211 }
212
213 void VLMPanel::OnLoad( wxCommandEvent &event )
214 {
215     p_file_dialog = new wxFileDialog( NULL, wxT(""), wxT(""), wxT(""),
216                                       wxT("*"), wxOPEN | wxMULTIPLE );
217     if( p_file_dialog == NULL ) return;
218
219     p_file_dialog->SetTitle( wxU(_("Load configuration") ) );
220     if( p_file_dialog->ShowModal() == wxID_OK )
221     {
222         vlm_Load( p_vlm->GetVLM(), p_file_dialog->GetPath().mb_str() );
223     }
224     Update();
225 }
226
227 void VLMPanel::OnSave( wxCommandEvent &event )
228 {
229     p_file_dialog = new wxFileDialog( NULL, wxT(""), wxT(""), wxT(""),
230                                       wxT("*"), wxSAVE | wxOVERWRITE_PROMPT );
231     if( p_file_dialog == NULL ) return;
232
233     p_file_dialog->SetTitle( wxU(_("Save configuration") ) );
234     if( p_file_dialog->ShowModal() == wxID_OK )
235     {
236         vlm_Save( p_vlm->GetVLM(), p_file_dialog->GetPath().mb_str() );
237     }
238 }
239
240 /*************************
241  * Broadcasts management
242  *************************/
243 wxPanel * VLMPanel::BroadcastPanel( wxWindow *parent )
244 {
245      broadcasts_panel = new wxPanel( parent, -1, wxDefaultPosition, wxSize( 500, 350 ) );
246      broadcasts_sizer = new wxBoxSizer( wxVERTICAL );
247
248      wxStaticBox *add_box = new wxStaticBox( broadcasts_panel, -1,
249                                             wxU( _( "New broadcast") ) );
250      wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer( add_box, wxHORIZONTAL );
251      box_sizer->Add( AddBroadcastPanel( broadcasts_panel), 0, wxEXPAND|wxALL, 5 );
252      box_sizer->Layout();
253
254      broadcasts_sizer->Add( box_sizer, 0, wxEXPAND|wxALL, 5 );
255
256      wxStaticLine *static_line = new wxStaticLine( broadcasts_panel, wxID_ANY );
257      broadcasts_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
258
259      scrolled_broadcasts = new wxScrolledWindow( broadcasts_panel, -1,
260                                 wxDefaultPosition, wxDefaultSize,
261                                 wxBORDER_NONE | wxVSCROLL );
262
263      scrolled_broadcasts_sizer = new wxBoxSizer( wxVERTICAL );
264      scrolled_broadcasts->SetAutoLayout( TRUE );
265      scrolled_broadcasts->SetScrollRate( 5,5 );
266      scrolled_broadcasts->SetSizerAndFit( scrolled_broadcasts_sizer );
267
268      broadcasts_sizer->Add( scrolled_broadcasts, 1, wxEXPAND| wxALL, 5 );
269      broadcasts_sizer->Layout();
270
271      broadcasts_panel->SetSizerAndFit( broadcasts_sizer );
272
273      return broadcasts_panel;
274 }
275
276 wxPanel * VLMPanel::AddBroadcastPanel( wxPanel *panel )
277 {
278      return new VLMAddStreamPanel( p_intf, panel, p_vlm, VLC_FALSE,
279                                    VLC_TRUE );
280 }
281
282 void VLMPanel::AppendBroadcast( VLMBroadcastStream *p_broadcast )
283 {
284     VLMBroadcastStreamPanel *p_new =
285                    new VLMBroadcastStreamPanel( p_intf, scrolled_broadcasts,
286                                                 p_broadcast );
287     p_new->b_found = VLC_TRUE;
288     scrolled_broadcasts_sizer->Add( p_new, 0, wxEXPAND | wxALL, 5 );
289     scrolled_broadcasts_sizer->Layout();
290     scrolled_broadcasts->FitInside();
291     broadcasts.push_back( p_new );
292 }
293
294 void VLMPanel::RemoveBroadcast( VLMBroadcastStreamPanel *p_streamp )
295 {
296     scrolled_broadcasts_sizer->Remove( p_streamp );
297     scrolled_broadcasts_sizer->Layout();
298     scrolled_broadcasts->FitInside();
299 }
300
301 /*************************
302  * VODS management
303  *************************/
304 wxPanel * VLMPanel::VODPanel( wxWindow *parent )
305 {
306      vods_panel = new wxPanel( parent, -1, wxDefaultPosition, wxSize( 500, 350 ) );
307      return vods_panel;
308 }
309
310 wxPanel * VLMPanel::AddVODPanel( wxPanel *panel )
311 {
312      return new VLMAddStreamPanel( p_intf, panel, p_vlm, VLC_FALSE,
313                                    VLC_FALSE );
314 }
315
316 void VLMPanel::AppendVOD( VLMVODStream *p_vod )
317 {
318     VLMVODStreamPanel *p_new =
319                    new VLMVODStreamPanel( p_intf, scrolled_vods, p_vod );
320     p_new->b_found = VLC_TRUE;
321     scrolled_vods_sizer->Add( p_new, 0, wxEXPAND | wxALL, 5 );
322     scrolled_vods_sizer->Layout();
323     scrolled_vods->FitInside();
324     vods.push_back( p_new );
325 }
326
327 void VLMPanel::RemoveVOD( VLMVODStreamPanel *p_streamp )
328 {
329     scrolled_vods_sizer->Remove( p_streamp );
330     scrolled_vods_sizer->Layout();
331     scrolled_vods->FitInside();
332 }
333
334 /****************************************************************************
335  * VLM Add Broadcast panel implementation
336  *****************************************************************************/
337 enum
338 {
339     Create_Event,
340     Clear_Event,
341     ChooseInput_Event,
342     ChooseOutput_Event,
343 };
344
345 BEGIN_EVENT_TABLE( VLMAddStreamPanel, wxPanel)
346    EVT_BUTTON( Create_Event, VLMAddStreamPanel::OnCreate )
347    EVT_BUTTON( Clear_Event, VLMAddStreamPanel::OnClear )
348    EVT_BUTTON( ChooseInput_Event, VLMAddStreamPanel::OnChooseInput )
349    EVT_BUTTON( ChooseOutput_Event, VLMAddStreamPanel::OnChooseOutput )
350 END_EVENT_TABLE()
351
352 VLMAddStreamPanel::VLMAddStreamPanel( intf_thread_t *_p_intf,
353                 wxWindow *_p_parent, VLMWrapper *_p_vlm,
354                 vlc_bool_t _b_edit, vlc_bool_t _b_broadcast ):
355                 wxPanel( _p_parent, -1, wxDefaultPosition, wxDefaultSize )
356 {
357     p_intf = _p_intf;
358     p_parent = _p_parent;
359     p_vlm = _p_vlm;
360     b_edit = _b_edit;
361     b_broadcast = _b_broadcast;
362
363     p_open_dialog = NULL;
364     p_sout_dialog = NULL;
365
366     SetAutoLayout( TRUE );
367
368     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
369
370     wxFlexGridSizer *upper_sizer = new wxFlexGridSizer( 5, 2 );
371     upper_sizer->AddGrowableCol( 1 );
372     upper_sizer->AddGrowableCol( 3 );
373
374     upper_sizer->Add( new wxStaticText( this, -1, wxU( _("Name") ) ), 0,
375                                         wxALIGN_CENTER_VERTICAL, 0 );
376     name_text = new wxTextCtrl( this, -1, wxU( "" ), wxDefaultPosition,
377                                           wxSize( 150, -1 ) );
378     upper_sizer->Add( name_text , 1, wxEXPAND | wxLEFT | wxRIGHT, 5 );
379
380     upper_sizer->Add( new wxStaticText( this, -1, wxU( _("Input") ) ), 0,
381                                         wxALIGN_CENTER_VERTICAL, 0 );
382     input_text = new wxTextCtrl( this, -1, wxU( "" ) ,
383                       wxDefaultPosition, wxSize( 150, -1 ) );
384     upper_sizer->Add( input_text , 1, wxEXPAND | wxLEFT | wxRIGHT, 5 );
385     upper_sizer->Add( new wxButton( this, ChooseInput_Event, wxU( _("Choose") )  ) );
386
387     upper_sizer->Add( 0,0 );
388     upper_sizer->Add( 0,0 );
389
390     upper_sizer->Add( new wxStaticText( this, -1, wxU( _("Output") ) ), 0,
391                                         wxALIGN_CENTER_VERTICAL, 0 );
392     output_text = new wxTextCtrl( this, -1, wxU( "" ) ,
393                       wxDefaultPosition, wxSize( 150, -1 ) );
394     upper_sizer->Add( output_text, 1, wxEXPAND | wxLEFT | wxRIGHT, 5 );
395     upper_sizer->Add( new wxButton( this, ChooseOutput_Event,
396                       wxU( _("Choose") )  ) );
397
398     panel_sizer->Add( upper_sizer, 0, wxEXPAND | wxALL, 5 );
399
400     wxBoxSizer *lower_sizer = new wxBoxSizer( wxHORIZONTAL );
401     enabled_checkbox = new wxCheckBox( this, -1, wxU( _("Enabled" ) ) );
402     enabled_checkbox->SetValue( true );
403     lower_sizer->Add( enabled_checkbox,  1 , wxEXPAND | wxALL , 5 );
404     if( b_broadcast )
405     {
406         loop_checkbox = new wxCheckBox( this, -1, wxU( _("Loop" ) ) );
407         lower_sizer->Add( loop_checkbox,  1 , wxEXPAND | wxALL , 5 );
408     }
409
410     if( !b_edit )
411     {
412         lower_sizer->Add( new wxButton( this, wxID_CLEAR ),
413                          0 , wxEXPAND | wxALL , 5 );
414     }
415     lower_sizer->Add( new wxButton( this, Create_Event,
416                           wxU( _( b_edit ? "OK" : "Create" ) ) ),
417                       0 , wxEXPAND | wxALL , 5 );
418
419
420     panel_sizer->Add( lower_sizer, 0 , wxEXPAND| wxALL, 5 );
421     panel_sizer->Layout();
422     SetSizerAndFit( panel_sizer );
423 }
424
425 VLMAddStreamPanel::~VLMAddStreamPanel()
426 {
427 }
428
429 void VLMAddStreamPanel::Load( VLMStream *p_stream )
430 {
431     name_text->SetValue( wxU( p_stream->p_media->psz_name ) );
432     name_text->SetEditable( false );
433     if( p_stream->p_media->i_input > 0 )
434     {
435         input_text->SetValue( wxU( p_stream->p_media->input[0] ) );
436     }
437     output_text->SetValue( wxU( p_stream->p_media->psz_output ) );
438     enabled_checkbox->SetValue( p_stream->p_media->b_enabled );
439     if( b_broadcast)
440         loop_checkbox->SetValue( p_stream->p_media->b_loop );
441 }
442
443 void VLMAddStreamPanel::OnCreate( wxCommandEvent &event )
444 {
445     char *psz_name = FromLocale( name_text->GetValue().mb_str() );
446     char *psz_input = FromLocale(  input_text->GetValue().mb_str() );
447     char *psz_output = FromLocale( output_text->GetValue().mb_str() );
448     if( b_broadcast && ! b_edit )
449     {
450         p_vlm->AddBroadcast( psz_name, psz_input, psz_output,
451                          enabled_checkbox->IsChecked() ? VLC_TRUE: VLC_FALSE,
452                          loop_checkbox->IsChecked() ? VLC_TRUE : VLC_FALSE );
453     }
454     else if( b_broadcast && b_edit )
455     {
456         p_vlm->EditBroadcast( psz_name, psz_input, psz_output,
457                         enabled_checkbox->IsChecked() ? VLC_TRUE: VLC_FALSE,
458                         loop_checkbox->IsChecked() ? VLC_TRUE : VLC_FALSE );
459     }
460     else if( !b_broadcast && !b_edit )
461     {
462         p_vlm->AddVod( psz_name, psz_input, psz_output,
463                        enabled_checkbox->IsChecked() ? VLC_TRUE: VLC_FALSE,
464                        loop_checkbox->IsChecked() ? VLC_TRUE : VLC_FALSE );
465     }
466     else
467     {
468         p_vlm->EditVod( psz_name, psz_input, psz_output,
469                         enabled_checkbox->IsChecked() ? VLC_TRUE: VLC_FALSE,
470                         loop_checkbox->IsChecked() ? VLC_TRUE : VLC_FALSE );
471     }
472     LocaleFree( psz_name) ; LocaleFree( psz_input ) ;
473     LocaleFree( psz_output);
474     if( !b_edit )
475         OnClear( event );
476     if( b_edit )
477         p_parent->Hide();
478 }
479
480 void VLMAddStreamPanel::OnClear( wxCommandEvent &event )
481 {
482     name_text->SetValue( wxU("") );
483     input_text->SetValue( wxU("") );
484     output_text->SetValue( wxU("") );
485 }
486
487 void VLMAddStreamPanel::OnChooseInput( wxCommandEvent &event )
488 {
489     if( p_open_dialog == NULL )
490         p_open_dialog = new OpenDialog( p_intf, this, -1, -1, OPEN_STREAM );
491
492     if( p_open_dialog && p_open_dialog->ShowModal() == wxID_OK )
493     {
494         input_text->SetValue( p_open_dialog->mrl[0] );
495     }
496 }
497
498 void VLMAddStreamPanel::OnChooseOutput( wxCommandEvent &event )
499 {
500     if( p_sout_dialog == NULL )
501         p_sout_dialog = new SoutDialog( p_intf, this );
502
503     if( p_sout_dialog && p_sout_dialog->ShowModal() == wxID_OK )
504     {
505         wxString sout = (p_sout_dialog->GetOptions())[0] ;
506         sout = sout.AfterFirst( '=' );
507         output_text->SetValue( sout );
508     }
509 }
510
511 /****************************************************************************
512  * VLM Frame implementation
513  ****************************************************************************/
514 enum
515 {
516 };
517
518 BEGIN_EVENT_TABLE( VLMFrame, wxFrame )
519     EVT_CLOSE( VLMFrame::OnClose )
520 END_EVENT_TABLE()
521
522 VLMFrame::VLMFrame( intf_thread_t *_p_intf, wxWindow *_p_parent ) :
523         wxFrame( _p_parent, -1, wxU( _("VLM configuration") ),
524         wxDefaultPosition, wxSize( 640,480 ), wxDEFAULT_FRAME_STYLE )
525 {
526     SetIcon( *_p_intf->p_sys->p_icon );
527
528     wxBoxSizer *main_sizer = new wxBoxSizer( wxHORIZONTAL );
529     vlm_panel = new VLMPanel( _p_intf, this );
530
531 #if defined(WIN32)
532     main_sizer->Add( vlm_panel, 1, wxGROW, 0 );
533 #else
534     main_sizer->Add( vlm_panel, 1, wxEXPAND | wxALL, 5 );
535 #endif
536     main_sizer->Layout();
537     SetSizerAndFit( main_sizer );
538 }
539
540 void VLMFrame::OnClose( wxCloseEvent& WXUNUSED(event) )
541 {
542     Hide();
543 }
544
545 void VLMFrame::Update()
546 {
547     vlm_panel->Update();
548 }
549
550 VLMFrame::~VLMFrame()
551 {
552     delete vlm_panel;
553 }
554
555 /****************************************************************************
556  * VLM Add stream Frame implementation
557  ****************************************************************************/
558 VLMEditStreamFrame::VLMEditStreamFrame( intf_thread_t *_p_intf,
559             wxWindow *_p_parent, VLMWrapper *_p_vlm, vlc_bool_t _b_broadcast,
560             VLMStream *p_stream ) :
561         wxFrame( _p_parent, -1, wxU( _("VLM stream") ),
562         wxDefaultPosition, wxSize( 640,480 ), wxDEFAULT_FRAME_STYLE )
563 {
564     SetIcon( *_p_intf->p_sys->p_icon );
565
566     wxBoxSizer *main_sizer = new wxBoxSizer( wxHORIZONTAL );
567     vlm_panel = new VLMAddStreamPanel( _p_intf, this, _p_vlm ,
568                                        VLC_TRUE, _b_broadcast );
569
570     vlm_panel->Load( p_stream );
571
572     main_sizer->Add( vlm_panel, 1, wxEXPAND | wxALL, 5 );
573     main_sizer->Layout();
574     SetSizerAndFit( main_sizer );
575 }
576
577 VLMEditStreamFrame::~VLMEditStreamFrame()
578 {
579 }