PLAYER

In questa sezione tratteremo la parte dettagliata del programma riguardante il riproduttore multimediale.

È  stato inserito un particolare oggetto chiamato AxWindowsMediaPlayer, vale a dire un ActiveX per la gestione dei file multimediali. L'oggetto propone al programmatore una serie di eventi e metodi  tipici di Windows Media Player, per esempio:

 

 

*       Immagini a tutto schermo

*       Gestione del volume

*       Bilanciamento casse

*       Ecc,ecc..

Detto questo ci basta generare l'evento desiderato e gestirlo di conseguenza, ad esempio:

     Private Sub canzoni_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles canzoni.DoubleClick

        Titolo.Text = "Titolo: "

        Autore.Text = "Autore: "

        Album.Text = "Album: "

 

        directory.SelectedIndex = canzoni.SelectedIndex

        AxWindowsMediaPlayer1.URL = GetItemText(canzoni.SelectedIndex)

        AxWindowsMediaPlayer1.newMedia(AxWindowsMediaPlayer1.URL)

        cursore.Maximum = CInt(AxWindowsMediaPlayer1.currentMedia.duration())

        cursore.Value = 0

 

        Timer_song.Start()

        Timer_tag.Start()

        playy.Visible = False

        pausee.Visible = True

        paused.Visible = True

        playd.Visible = False

        scorre.Text = "  " & canzoni.SelectedItem

 

    End Sub

 

    Private Sub canzoni_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles canzoni.KeyPress

        If e.KeyChar = Microsoft.VisualBasic.ChrW(13) Then

            Titolo.Text = "Titolo: "

            Autore.Text = "Autore: "

            Album.Text = "Album: "

             directory.SelectedIndex = canzoni.SelectedIndex

            AxWindowsMediaPlayer1.URL = GetItemText(canzoni.SelectedIndex)

            AxWindowsMediaPlayer1.newMedia(AxWindowsMediaPlayer1.URL)

            cursore.Maximum = CInt(AxWindowsMediaPlayer1.currentMedia.duration())

            cursore.Value = 0

            Timer_song.Start()

            Timer_tag.Start()

            playy.Visible = False

            pausee.Visible = True

            paused.Visible = True

            playd.Visible = False

            scorre.Text = "  " & canzoni.SelectedItem

        End If

    End Sub

 

Il codice di cui sopra serve per la gestione delle canzoni selezionate da una  listbox chiamata canzoni. Tenendo conto che l'oggetto ActiveX è ingordo di suonare solo percorsi standard, è necessario sincronizzare la lista canzoni con una lista directory col seguente metodo:

 directory.SelectedIndex = canzoni.SelectedIndex

 

il resto del codice è semplice, queste due righe servono appunto a riprodurre il file selezionato:

 AxWindowsMediaPlayer1.URL = GetItemText(canzoni.SelectedIndex)

AxWindowsMediaPlayer1.newMedia(AxWindowsMediaPlayer1.URL)

 È possibile notare un metodo particolare associato alla list box : GetItemText. Il metodo restituisce il testo associato all'indice della lista box che gli viene passato come parametro. Il procedimento come si può vedere non è difficile bisogna solo entrare nell'ottica di gestione di ogni singolo evento che l'utente può generare.La parte più complessa è stata la gestione del tempo e del cursore di posizione. Il valore del cursore di posizione (da qui in poi seek) dove assumere il valore della posizione della canzone in quell'istante.

Ecco il codice:

 #Region "Tempo traccia"

    Private Sub Timer_song_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer_song.Tick

        total = CInt(AxWindowsMediaPlayer1.Ctlcontrols.currentPosition())

        cursore.Maximum = CInt(AxWindowsMediaPlayer1.currentMedia.duration())

        cursore.Value = total

        second = CInt(AxWindowsMediaPlayer1.Ctlcontrols.currentPosition())

        ore = second \ 3600

        min = second \ 60  

        sec = second - (min * 60)

        ore = 0

        If sec = "-1" Then sec = "0"

 

        If min >= 60 Then

            min = min - 60

            ore = ore + 1 

        End If

        If sec < 10 And min < 10 Then

            tempo.Text = CStr(canzoni.SelectedItem) & "   " & "0" & ore & ":0" & min & ":0" & sec

        ElseIf sec >= 10 And min >= 10 Then

            tempo.Text = CStr(canzoni.SelectedItem) & "   " & "0" & ore & ":" & min & ":" & sec

 

        ElseIf sec < 10 And min >= 10 Then

            tempo.Text = CStr(canzoni.SelectedItem) & "   " & "0" & ore & ":" & min & ":0" & sec

 

        ElseIf sec >= 10 And min < 10 Then

            tempo.Text = CStr(canzoni.SelectedItem) & "   " & "0" & ore & ":0" & min & ":" & sec

        End If

 

 

    End Sub

#End Region

 

Come intercettare la posizione della canzone?

L'activeX ci viene in aiuto:

cursore.value=AxWindowsMediaPlayer.CurrentMedia.CurrentPosition

La proprietà CurrentMedia ci consente di intercettare il file che si sta utilizzando e CurrentPosition catture la sua posizione espressi in secondi dall'inizio del file.Date queste brevi premesse parleremo ora delle parti più interessanti del programma dividendole in parte Multimediale e Browser. Perchè all'inizio e alla fine  di ogni blocco di codice compare

 

#Region "[testo]"

 

#End Region ?

 

Questa semplice istruzione permette di racchiuder il codice un un'area facilmente riconoscibile grazie la testo che noi scriviamo tra i due apici (al posto della scritta [testo]). In pratica è utile per individuare le parti del programma o che non funzionano correttamente o da cambiare, oppure semplicemente per organizzare il codice in modo che sia più comprensibile. Di seguito viene commentato tutto l'algoritmo utilizzato per aprire i file multimediali:

 

    Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click

        On Error GoTo Fix

        OpenFileDialog2.Filter = "ALL MUSIC FILES|*.mp3;*.wma;*.wave;*.wav;*.mid;*.midi;*.cda|Video Formats|*.avi;*.divx; *.xvid; *.vob;*.mpeg"

 

Il blocco sopra definisce semplicemente quali tipi di file devono essere riprodotti

 

OpenFileDialog2.ShowDialog()

Viene mostrata la finestra di apertura

 

 

       

        If OpenFileDialog2.FileNames.Length > 0 Then

 

Per avere la selezione multipla delle canzoni basta utilizzare la proprietà filenames

 

            directory.Items.Clear()

            canzoni.Items.Clear()

 

 

            Me.AxWindowsMediaPlayer1.Ctlcontrols.stop()

 

Qui vengono aggiornate le liste con le nuove canzoni cancellando le vecchie. La proprietà filenames mi restituisce una matrice che è quindi necessario scorrere vere potere "utilizzare" tutte le voci in essa contenute, ecco come:

 

            Dim canzone As String

            For Each canzone In OpenFileDialog2.FileNames

                Dim file As String = canzone

                directory.Items.Add(file)

 

Le seguenti variabile mi servono per gestire la visualizzazione del solo titolo della canzone

 

                Dim s As String         

                Dim s2 As Object

                Dim sR As String

                 s = canzone

 dichiarazione della canzone(in realtà si tratta della path)

                 sR = StrReverse(s)

 Questo blocco mi rovescia la stringa

 

                s2 = s.Substring(Len(s) - sR.IndexOf("\"))

 

Dalla stringa rovesciata posso prelevare tutto ciò che è dopo la \ (vale a dire il titolo della canzone più la sua estensione), e l'aggiungo alle altre

 

                canzoni.Items.Add(s2)

 ripetuto per tutte le voci della matrice

                 canzoni.SelectedItem = s2

                OpenFileDialog2.FileName = ""

            Next

        End If

 Qui sotto vengono azzerate le etichette per la visualizzazione dei tag:

 

        Titolo.Text = "Titolo: "

        Autore.Text = "Autore: "

        Album.Text = "Album: "

 

Seleziono poi la prima voce:

 

        directory.SelectedIndex = 0

        canzoni.SelectedIndex = 0

 

Sincronizzo le due liste:

 

        canzoni.SelectedIndex = directory.SelectedIndex

 

Visualizzo i pulsanti che mi interessano

 

        pausee.Visible = False

        playy.Visible = True

        playd.Visible = True

        paused.Visible = False

       Fix:

        Exit Sub

    End Sub

 

 

La parte che segue è un commento allo sviluppo del movimento della barra di seek

 

#Region "Barra di scorrimento"

    Private Sub cursore_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cursore.Scroll

        'Decido il punto della canzone

        AxWindowsMediaPlayer1.Ctlcontrols.currentPosition = cursore.Value

    End Sub

    Private Sub cursore_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cursore.ValueChanged

        If cursore.Value = cursore.Maximum - 1 Then

            If canzoni.SelectedIndex = canzoni.Items.Count Then 'se è l'ultimo elemento mi fermo

                Me.AxWindowsMediaPlayer1.Ctlcontrols.stop()

                Me.AxWindowsMediaPlayer1.URL = ""

                Me.AxWindowsMediaPlayer1.newMedia("")

            End If

            If caso.Checked = True Then

                v = objRandom.Next(0, (directory.Items.Count))               

                directory.SelectedIndex = v

                v = objRandom.Next(0, (canzoni.Items.Count))

                canzoni.SelectedIndex = v

                directory.SelectedIndex = canzoni.SelectedIndex

                Me.AxWindowsMediaPlayer1.URL = GetItemText(directory.SelectedIndex)

                Me.AxWindowsMediaPlayer1.newMedia(Me.AxWindowsMediaPlayer1.URL)

                scorre.Text = canzoni.SelectedItem

             End If

            If directory.SelectedIndex < directory.Items.Count - 1 Then

                directory.SelectedIndex = canzoni.SelectedIndex

                directory.SelectedIndex = directory.SelectedIndex + 1

                canzoni.SelectedIndex = canzoni.SelectedIndex + 1

                directory.SelectedIndex = canzoni.SelectedIndex

                AxWindowsMediaPlayer1.URL = GetItemText(directory.SelectedIndex)

                AxWindowsMediaPlayer1.newMedia(AxWindowsMediaPlayer1.URL)

                scorre.Text = canzoni.SelectedItem

            End If

 

        End If

        voice.Visible = False

        mute.Visible = True

      End Sub

#End Region

 

Questa parte di codice, fa questa semplice operazione: ogni volta che la posizione della barra seek cambia, viene controllata se questo valore corrisponde al valore massimo meno uno della barra stessa, in caso affermativo, viene controllato se la voce riproduzione casuale è selezionata, se si, si riproduce casualmente un brano, altrimenti si somma uno si alla lista delle path, sia alla lista dei titoli delle canzoni, le sincronizzo col solito metodo, poi le suono. Ogni player che si rispetti permette anche la creazione delle plyelist, ovviamente il nostro non poteva essere da meno.Per farle abbiamo deciso di utilizzare una potente tecnologia messa a disposizione dallo stesso ambiente di sviluppo: XML

Ecco il metodo utilizzato per scrivere un file XML:

 

    Private Sub Write_XML()

        Dim XMLobj As Xml.XmlTextWriter

        Dim ue As New System.[Text].UnicodeEncoding

        XMLobj = New Xml.XmlTextWriter(Application.StartupPath & "\" & "Playlist" & "\" &    titololista.Text & ".xml", ue)

        XMLobj.Formatting = Xml.Formatting.Indented

        XMLobj.Indentation = 3

        XMLobj.WriteStartDocument()

        XMLobj.WriteStartElement("List")

        Dim i As Integer

        For i = 0 To directory.Items.Count - 1

            XMLobj.WriteStartElement("MP3_File")

            Dim temp As String = ""

            Dim temp1 As String = ""

            directory.SetSelected(i, True)

            canzoni.SetSelected(i, True)

            temp = directory.SelectedItem

            temp1 = canzoni.SelectedItem

            XMLobj.WriteAttributeString("File", temp)

            XMLobj.WriteAttributeString("Title", temp1)

            XMLobj.WriteEndElement()

        Next

        XMLobj.WriteEndElement()

        XMLobj.Close()

    End Sub

 

Il codice sovrastante ha come effetto un file XML strutturato così:

 

 

 

  

 

Il file ha una struttura molto semplice: nel tag file viene scritto il percorso, nel tag titolo il solo titolo del brano o del video in modo che in lettura siano facilmente recuperabili tramite il codice che segue:

 

        Private Sub Read_XML()

        Dim XMLReader As Xml.XmlReader

        XMLReader = New Xml.XmlTextReader(fl.Path & "\" & fl.Text)

        While XMLReader.Read

            Select Case XMLReader.NodeType

                Case Xml.XmlNodeType.Element

                    If XMLReader.AttributeCount > 0 Then

                        While XMLReader.MoveToNextAttribute

                            If XMLReader.Name = "File" Then

                                directory.Items.Add(XMLReader.Value)

                            ElseIf XMLReader.Name = "Title" Then

                                canzoni.Items.Add(XMLReader.Value)

                            Else

                                ' Do Nothing

                            End If

                        End While

                    End If

            End Select

        End While

        XMLReader.Close()

        playy.Visible = False 'play

        pausee.Visible = True 'pausa

        paused.Visible = True 'pausa

        playd.Visible = False 'play

    End Sub

 

In questa funzione viene letto campo per campo e aggiornate le liste di conseguenza. Ogni lista viene aggiornata con la voce opportuna. Abbiamo optato per la scelta di questo strumento per la sua semplicità di utilizzo per l'immediatezza della comprensione. La regolazione del volume è stato per una intera settimana il nostro maggiore grattacapo  perché non riuscivamo a gestirlo in tempo reale poi abbiamo deciso di utilizzare  una variabile per intercettare il valore del cursore utilizzato per la regolazione del volume e assegnare poi questo valore alla proprietà volume dell'ActiveX.

 

    Private Sub volume_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles volume.Scroll

        Dim vo As Integer 'variabile per il volume

        '

        vo = volume.Value

        'Settaggio volume

        Me.AxWindowsMediaPlayer1.settings.volume = vo

        Dim foo As Integer

        On Error GoTo Fix

        'valore del volume

 

        foo = volume.Value

        tivol.Text = "Volume: " & foo & "%"

Fix:

        Exit Sub

 

Idem dicasi per il bilanciamento delle casse:

Abbiamo settato prima il valore minimo (-500)  e poi il valore massimo (500) e poi abbiamo intercettato il valore del cursore utilizzato per la gestione del bilanciamento e assegnato questo valore alla proprietà balance  dell'ActiveX.

 

Private Sub bil_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bil.Scroll

        On Error GoTo Fix

        Dim bila As Integer

        bila = bil.Value * (-1)

        If bil.Value > -500 And bil.Value < 500 Then

            tibil.Text = "Bilanciamento: Centro"

        End If

        If bil.Value < -500 Then

            Me.AxWindowsMediaPlayer1.settings.balance = Me.AxWindowsMediaPlayer1.settings.balance / 50

            tibil.Text = "Bilanciamento: Sinistra"

        End If

        If bil.Value > 500 Then

            Me.AxWindowsMediaPlayer1.settings.balance = Me.AxWindowsMediaPlayer1.settings.balance / 50

            tibil.Text = "Bilanciamento: Destra"

        End If

        Me.AxWindowsMediaPlayer1.settings.balance = bila

 

Fix:

        Exit Sub

    End Sub

 

 

 

 

Un altro problema che ci siamo posti è sto quello di evitare di usare la solita forma della finestra di programmazione. A questo riguardo ci siamo serviti di una libreria per il disegno 2d

 

Imports System.Drawing.Drawing2D

 

Istanziando poi questa libreria  abbiamo ottenuto una form non più rettangolare

 

    Private Sub SetFormRegion()

        'Preferisco non esprimermi

        gp.AddLine(16, 0, Width - 32, 0)

        gp.AddArc(Width - 32, 0, 32, 32, 270, 90)

        gp.AddLine(Width, 16, Width, Height - 32)

        gp.AddArc(Width - 32, Height - 32, 32, 32, 0, 90)

        gp.AddLine(Width - 32, Height, 16, Height)

        gp.AddArc(0, Height - 32, 32, 32, 90, 90)

        gp.AddLine(0, Height - 32, 0, 32)

        gp.AddArc(0, 0, 32, 32, 180, 90)

        gp.CloseFigure()

        Me.Region = New Region(gp)

    End Sub

 

 

Poi basta chiamare questa funzione (call SetFormRegion) quando lo si ritiene necessario (preferibilmente nell'evento load del form). Qui di seguito viene riportata la procedura per avere form con forme molto diverse:

La creazione di form non rettangolari è costituita da due parti: la creazione del form con la forma desiderata e la creazione della logica di programmazione per consentire lo spostamento e la chiusura del form. Questa seconda fase è necessaria poiché un form con una forma personalizzata non ha barra del titolo e non dispone di funzionalità intrinseche, come la possibilità di spostamento sullo schermo e di chiusura. È pertanto necessario scrivere il codice appropriato per replicare queste funzionalità. La creazione di un form non rettangolare è costituita da tre fasi: Creare una bitmap con la funzione di superficie del form. Si tratta in effetti di ritagliare la forma desiderata da un rettangolo.  Creare un progetto di applicazione Windows e impostarne le proprietà in modo da eliminare la barra del titolo e utilizzare la bitmap come sfondo del form.  Immettere il codice per ricreare le funzionalità fornite dalla barra del titolo, ad esempio lo spostamento e la chiusura del form.

 

Per creare un form con forma personalizzata

Creare una bitmap di forma non rettangolare di un colore con uno sfondo in un altro colore. Utilizzare il programma di disegno desiderato. Poiché la forma disegnata corrisponderà al form, realizzare un disegno di dimensioni sufficientemente grandi.

 

Nota:   Scegliere un colore di sfondo facile da ricordare, come il blu, poiché sarà importante in seguito.

 

Nella finestra Proprietà: Impostare la proprietà FormBorderStyle su None. Viene rimossa la barra del titolo dal form. Vengono anche rimosse le funzionalità fornite dalla barra del titolo, come la possibilità di chiudere e di spostare il form. Questo problema verrà risolto nel codice in un secondo momento. Impostare la proprietà BackgroundImage del form sul file bitmap creato in precedenza.Non occorre aggiungere il file al sistema del progetto, poiché questa operazione è automatica quando si specifica il file come immagine di sfondo. Con questa proprietà l'immagine bitmap viene impostata come sfondo del form. Quando la si utilizza con la proprietà TransparencyKey specificata di seguito, questa proprietà definisce la forma del form. Impostare la proprietà TransparencyKey sul colore di sfondo del file bitmap. Con questa proprietà si segnala all'applicazione quali parti del form saranno trasparenti.

 Nota:    È possibile che sui monitor impostati con un'intensità colore superiore a 24 bit si presentino problemi di visualizzazione, con la conseguenza che determinate parti del form non appaiano trasparenti nonostante l'impostazione della proprietà TransparencyKey. Per evitare questo problema, accertarsi che l'intensità colore del monitor sia impostata su un valore inferiore a 24 bit nel pannello di controllo Schermo.

 Nello sviluppo di applicazioni che prevedono l'applicazione della trasparenza, è opportuno informare gli utenti in merito a questo inconveniente.

Per scrivere il codice per chiudere il form

Aggiungere un controllo Button al form.  Aggiungere codice per consentire all'utente di chiudere il form richiamando il metodo Close. Nell'esempio seguente viene illustrato come aggiungere un pulsante mediante la scelta del quale sia possibile chiudere il form.

 

Private Sub Button1_Click(ByVal sender As System.Object, _

   ByVal e As System.EventArgs) Handles Button1.Click

   Me.Close()

End Sub

 

Per scrivere il codice per spostare il form (facoltativo)

Creare una routine per spostare il form quando lo si trascina. Immettere codice simile a quello riportato di seguito per creare un nuovo oggetto Point. Questo codice avrà la funzione di una variabile quando si calcola come spostare il form. Il campo isMouseDown viene utilizzato per tenere traccia della pressione del pulsante del mouse. Il form verrà spostato solo mentre si tiene premuto il pulsante del mouse.

 

' Visual Basic

Private mouseOffset As Point

Private isMouseDown As Boolean = False

 

' Visual Basic

Private Sub Form1_MouseDown(ByVal sender As Object, _

    ByVal e As MouseEventArgs) Handles MyBase.MouseDown

    Dim xOffset As Integer

    Dim yOffset As Integer

 

    If e.Button = MouseButtons.Left Then

        xOffset = -e.X - SystemInformation.FrameBorderSize.Width

        yOffset = -e.Y - SystemInformation.CaptionHeight - _

                SystemInformation.FrameBorderSize.Height

        mouseOffset = New Point(xOffset, yOffset)

        isMouseDown = True

    End If

End Sub

 

Creare un gestore eventi per l'evento MouseMove del form.

Immettere codice simile a quello riportato di seguito. Quando si fa clic sul pulsante sinistro e si trascina il mouse, la proprietà Location del form viene impostata sulla nuova posizione.

 

' Visual Basic

Private Sub Form1_MouseMove(ByVal sender As Object, _

    ByVal e As MouseEventArgs) Handles MyBase.MouseMove

    If isMouseDown Then

        Dim mousePos As Point = Control.MousePosition

        mousePos.Offset(mouseOffset.X, mouseOffset.Y)

        Location = mousePos

    End If

End Sub

   Creare un gestore eventi per l'evento MouseUp del form.

  Immettere codice simile a quello riportato di seguito.

 

Private Sub Form1_MouseUp(ByVal sender As Object, _

    ByVal e As MouseEventArgs) Handles MyBase.MouseUp

    ' Changes the isMouseDown field so that the form does

    ' not move unless the user is pressing the left mouse button.

    If e.Button = MouseButtons.Left Then

        isMouseDown = False

    End If

End Sub

 

Il programma prevede anche la lettura dei tag.Questo avviene tramite dei metodi dell'ActiveX (GetItemByInfo) e passandogli per parametro il nome del tag che vogliamo leggere, questa informazione ci verrà restituita sottoforma di  stringhe. Per visualizzarle basterà abbinare le stringhe a un qualsiasi oggetto che preveda un testo (es. textbox,label ecc.)

Ecco il risultato di tutto