From: <moi...@us...> - 2007-02-01 00:58:53
|
Revision: 70 http://mp-plugins.svn.sourceforge.net/mp-plugins/?rev=70&view=rev Author: moiristo Date: 2007-01-31 16:58:51 -0800 (Wed, 31 Jan 2007) Log Message: ----------- A new version of IPTV@UT Modified Paths: -------------- trunk/plugins/IPTV@UT/IPTV@UT/ConfigurationForm.cs trunk/plugins/IPTV@UT/IPTV@UT/IPTV.cs trunk/plugins/IPTV@UT/IPTV@UT/IPTV@UT.csproj trunk/plugins/IPTV@UT/IPTV@UT/IPTVPlugin.cs trunk/plugins/IPTV@UT/IP...@UT...o trunk/plugins/MyTorrents/c3o.plugins.suo trunk/plugins/UitzendingGemist/UitGemist.suo trunk/plugins/VideoLAN/ConfigurationForm.cs trunk/plugins/VideoLAN/VideoLanPlugin.cs trunk/plugins/VideoLAN/VlcUserControl.cs Added Paths: ----------- trunk/plugins/IPTV@UT/[ Default Skin ]/MyIPTV.xml Removed Paths: ------------- trunk/plugins/IPTV@UT/[ Default Skin ]/MP_0.2.1/ trunk/plugins/IPTV@UT/[ Default Skin ]/MP_0.2.1_SVN/ trunk/plugins/IPTV@UT/[ Project Mayhem 3 ]/ Modified: trunk/plugins/IPTV@UT/IPTV@UT/ConfigurationForm.cs =================================================================== --- trunk/plugins/IPTV@UT/IPTV@UT/ConfigurationForm.cs 2007-01-31 22:29:16 UTC (rev 69) +++ trunk/plugins/IPTV@UT/IPTV@UT/ConfigurationForm.cs 2007-02-01 00:58:51 UTC (rev 70) @@ -7,7 +7,7 @@ using System.Text; using System.Windows.Forms; using MediaPortal.GUI.Library; -using MediaPortal.Util; +using MediaPortal.Utils; namespace MediaPortal.GUI.IPTV { Modified: trunk/plugins/IPTV@UT/IPTV@UT/IPTV.cs =================================================================== --- trunk/plugins/IPTV@UT/IPTV@UT/IPTV.cs 2007-01-31 22:29:16 UTC (rev 69) +++ trunk/plugins/IPTV@UT/IPTV@UT/IPTV.cs 2007-02-01 00:58:51 UTC (rev 70) @@ -3,7 +3,6 @@ using MediaPortal.Util; using MediaPortal.Dialogs; using MediaPortal.Playlists; -using MediaPortal.VideoLanPlugin; using System.Drawing; using System.IO; @@ -12,8 +11,12 @@ public class IPTV : GUIWindow { #region SkinControlAttributes - [SkinControlAttribute(2)] + [SkinControlAttribute(19)] + protected GUIListControl listview = null; + [SkinControlAttribute(21)] protected GUIButtonControl btnLoad = null; + [SkinControlAttribute(22)] + protected GUIButtonControl btnRecordings = null; [SkinControlAttribute(99)] protected GUIVideoControl videoWindow = null; #endregion @@ -22,9 +25,11 @@ private static int currentChannel = 0; private static PlayListVLCIO plvi = new PlayListVLCIO(); private static VirtualDirectory plDirectory = new VirtualDirectory(); + private static VirtualDirectory recDirectory = new VirtualDirectory(); private static string playListPath; private static OnActionHandler ah; - private static bool inited = false; + private static bool inited = false; + private static string vlciptvdir = Directory.GetCurrentDirectory() + @"\vlciptv"; public override int GetID { @@ -54,6 +59,14 @@ share.Path = playListPath; plDirectory.IsRootShare(playListPath); + recDirectory.AddExtension(".ts"); + recDirectory.ShowFilesWithoutExtension = false; + + Share share2 = new Share(); + share2.Name = "Recordings"; + share2.Path = vlciptvdir; + recDirectory.IsRootShare(vlciptvdir); + if(ah == null) ah = new OnActionHandler(OnAction2); return result; @@ -62,7 +75,8 @@ public void OnAction2(Action action) { if (GUIWindowManager.ActiveWindowEx == (int) GUIWindow.Window.WINDOW_DIALOG_MENU) return; - + bool actionTaken = true; + switch (action.wID) { case Action.ActionType.ACTION_PREV_CHANNEL: @@ -121,8 +135,13 @@ Play(currentChannel); break; } + break; + default: + actionTaken = false; break; } + + if(actionTaken) listview.SelectedListItemIndex = currentChannel; } public override void OnAction(Action action) @@ -141,16 +160,16 @@ } protected override void OnClicked(int controlId, GUIControl control, Action.ActionType actionType) - { + { if (control == btnLoad) { - if (g_Player.Playing) g_Player.Stop(); - GUIDialogSelect diag = (GUIDialogSelect)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_SELECT); + GUIDialogSelect diag = (GUIDialogSelect)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_SELECT); diag.SetHeading("Choose Playlist"); diag.Reset(); + diag.IsOverlayAllowed = true; foreach (GUIListItem item in plDirectory.GetDirectory(playListPath)) { - if(!item.IsFolder) diag.Add(item.Label); + if (!item.IsFolder) diag.Add(item.Label); } diag.EnableButton(true); diag.SetButtonLabel("Load Playlist"); @@ -159,11 +178,48 @@ // and wait till user selects one, then load it immediately string selected = diag.SelectedLabelText; - if(File.Exists(playListPath + @"\" + selected + ".vlc")) - LoadAndPlay(playListPath + @"\" + selected + ".vlc"); - else LoadAndPlay(playListPath + @"\" + selected + ".m3u"); + if (!selected.Trim().Equals("")) + { + if (File.Exists(playListPath + @"\" + selected + ".vlc")) + LoadAndPlay(playListPath + @"\" + selected + ".vlc"); + else LoadAndPlay(playListPath + @"\" + selected + ".m3u"); + } } + if (control == btnRecordings) + { + GUIDialogSelect diag = (GUIDialogSelect)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_SELECT); + diag.SetHeading("Available Recordings"); + diag.Reset(); + diag.IsOverlayAllowed = true; + foreach (GUIListItem item in recDirectory.GetDirectory(vlciptvdir)) + { + if (!item.IsFolder) diag.Add(item.Label); + } + diag.EnableButton(true); + diag.SetButtonLabel("Load Recording"); + diag.DoModal(GUIWindowManager.ActiveWindow); + // and wait till user selects one, then load it immediately + string selected = diag.SelectedLabelText; + + if (!selected.Trim().Equals("")) + { + GUIGraphicsContext.IsFullScreenVideo = false; + g_Player.Play(vlciptvdir + @"\" + selected + ".ts"); + GUIPropertyManager.SetProperty("#IPTV.View.channel", selected); + } + } + if (control == listview && actionType == Action.ActionType.ACTION_SELECT_ITEM) + { + if (listview.SelectedListItemIndex == -1) return; + else + { + currentChannel = listview.SelectedListItemIndex; + Play(currentChannel); + } + } + listview.SelectedListItemIndex = currentChannel; + base.OnClicked(controlId, control, actionType); } @@ -191,10 +247,16 @@ GUIPropertyManager.SetProperty("#IPTV.View.channel", ""); // Read a playlist, if configured, and start playing it LoadAndPlay(GetDefaultPlayList()); - inited = true; } - + + foreach (PlayListItem item in playlist) + { + GUIListItem litem = new GUIListItem(); + litem.Label = item.Description; + litem.IconImage = "check-box.png"; + listview.Add(litem); + } } protected override void OnPageDestroy(int new_windowId) @@ -205,20 +267,20 @@ protected override void OnShowContextMenu() { - if (playlist.Count == 0) return; + //if (playlist.Count == 0) return; - GUIDialogMenu menu = (GUIDialogMenu)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU); - menu.Reset(); + //GUIDialogMenu menu = (GUIDialogMenu)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU); + //menu.Reset(); - menu.SetHeading("Channel List"); - foreach (PlayListItem item in playlist) - menu.Add(item.Description); - if (menu.SelectedId == -1) return; - else - { - currentChannel = menu.SelectedId - 1; - Play(currentChannel); - } + //menu.SetHeading("Channel List"); + //foreach (PlayListItem item in playlist) + // menu.Add(item.Description); + //if (menu.SelectedId == -1) return; + //else + //{ + // currentChannel = menu.SelectedId - 1; + // Play(currentChannel); + //} base.OnShowContextMenu(); } @@ -231,7 +293,7 @@ playlist.Clear(); bool result = plvi.Load(playlist, plFile); if (result) - { + { if (currentChannel < playlist.Count) Play(currentChannel); else if (playlist.Count > 0) Play(0); } @@ -257,7 +319,7 @@ plDir = reader.GetValueAsString("settings", "PlayListDir", ""); } return plDir; - } + } public static void Play(int plIndex) { @@ -267,7 +329,7 @@ Log.Info("MyIPTV: Trying to play channel '" + item.Description + "' (" + item.FileName + ")."); GUIGraphicsContext.IsFullScreenVideo = false; g_Player.Play(item.FileName); - GUIPropertyManager.SetProperty("#IPTV.View.channel", item.Description); + GUIPropertyManager.SetProperty("#IPTV.View.channel", item.Description); } } } \ No newline at end of file Modified: trunk/plugins/IPTV@UT/IPTV@UT/IPTV@UT.csproj =================================================================== --- trunk/plugins/IPTV@UT/IPTV@UT/IPTV@UT.csproj 2007-01-31 22:29:16 UTC (rev 69) +++ trunk/plugins/IPTV@UT/IPTV@UT/IPTV@UT.csproj 2007-02-01 00:58:51 UTC (rev 70) @@ -28,24 +28,24 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> - <Reference Include="Core, Version=1.0.2524.28381, Culture=neutral, processorArchitecture=MSIL"> + <Reference Include="Core, Version=1.0.2586.6922, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\..\trunk\mediaportal\xbmc\bin\Release\Core.dll</HintPath> + <HintPath>..\..\..\trunk\mediaportal\Core\bin\Release\Core.dll</HintPath> </Reference> <Reference Include="Dialogs, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\..\trunk\mediaportal\Dialogs\bin\Release\Dialogs.dll</HintPath> + <HintPath>..\..\..\trunk\mediaportal\Dialogs\bin\Release\Dialogs.dll</HintPath> </Reference> - <Reference Include="ExternalPlayers, Version=1.0.2543.36238, Culture=neutral, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\..\trunk\mediaportal\ExternalPlayers\bin\Release\ExternalPlayers.dll</HintPath> - </Reference> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.DirectoryServices" /> <Reference Include="System.Drawing" /> <Reference Include="System.Windows.Forms" /> <Reference Include="System.Xml" /> + <Reference Include="Utils, Version=1.0.2586.6921, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\trunk\mediaportal\Utils\bin\Release\Utils.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> <Compile Include="ConfigurationForm.cs"> @@ -75,4 +75,7 @@ <Target Name="AfterBuild"> </Target> --> + <PropertyGroup> + <PostBuildEvent>xcopy $(TargetPath) D:\MediaPortal\trunk\mediaportal\xbmc\bin\Release\plugins\windows\ /y</PostBuildEvent> + </PropertyGroup> </Project> \ No newline at end of file Modified: trunk/plugins/IPTV@UT/IPTV@UT/IPTVPlugin.cs =================================================================== --- trunk/plugins/IPTV@UT/IPTV@UT/IPTVPlugin.cs 2007-01-31 22:29:16 UTC (rev 69) +++ trunk/plugins/IPTV@UT/IPTV@UT/IPTVPlugin.cs 2007-02-01 00:58:51 UTC (rev 70) @@ -37,7 +37,7 @@ // Returns the name of the plugin which is shown in the plugin menu public string PluginName() { - return "My IPTV"; + return "VLC IPTV"; } // Returns the description of the plugin is shown in the plugin menu Modified: trunk/plugins/IPTV@UT/IP...@UT...o =================================================================== (Binary files differ) Added: trunk/plugins/IPTV@UT/[ Default Skin ]/MyIPTV.xml =================================================================== --- trunk/plugins/IPTV@UT/[ Default Skin ]/MyIPTV.xml (rev 0) +++ trunk/plugins/IPTV@UT/[ Default Skin ]/MyIPTV.xml 2007-02-01 00:58:51 UTC (rev 70) @@ -0,0 +1,91 @@ +<window> + <id>7500</id> + <defaultcontrol>19</defaultcontrol> + <allowoverlay>no</allowoverlay> + <define>#header.label:My IPTV</define> + <define>#header.image:</define> + <define>#header.hover:hover_my tv.png</define> + <controls> + <import>common.window.xml</import> + <control> + <type>image</type> + <description>background image</description> + <id>1</id> + <posX>0</posX> + <posY>0</posY> + <texture>background.png</texture> + </control> + <control> + <type>listcontrol</type> + <description>afleveringen</description> + <id>19</id> + <posX>290</posX> + <posY>97</posY> + <width>410</width> + <onup>17</onup> + <font2>font10</font2> + <font3>font10</font3> + <textureHeight>25</textureHeight> + <IconYOff>3</IconYOff> + <textYOff>0</textYOff> + </control> + <control> + <type>videowindow</type> + <description>video window</description> + <id>99</id> + <posX>30</posX> + <posY>190</posY> + <width>224</width> + <height>136</height> + <colordiffuse>ffffffff</colordiffuse> + <onright>19</onright> + <onup>17</onup> + <ondown>21</ondown> + <animation>WindowClose</animation> + <action>18</action> + <textureFocus>tv_green_border.png</textureFocus> + </control> + + <control> + <type>group</type> + <description>group element</description> + <animation effect="fade" time="250">WindowOpen</animation> + <animation effect="fade" time="500">WindowClose</animation> + <animation effect="slide" time="250" start="-300,0">WindowOpen</animation> + <animation effect="slide" time="500" end="0,-300">WindowClose</animation> + <layout>StackLayout</layout> + <posX>45</posX> + <posY>420</posY> + <control> + <type>button</type> + <description>Load playlist button</description> + <id>21</id> + <onright>19</onright> + <onup>99</onup> + <ondown>22</ondown> + <label>Load Playlist</label> + </control> + <control> + <type>button</type> + <description>Recordings button</description> + <id>22</id> + <onright>19</onright> + <onup>21</onup> + <ondown>19</ondown> + <label>Recordings</label> + </control> + </control> + + <control> + <type>fadelabel</type> + <description>Current Channelname</description> + <id>13</id> + <posX>32</posX> + <posY>152</posY> + <width>224</width> + <align>left</align> + <label>#IPTV.View.channel</label> + <textcolor>white</textcolor> + </control> + </controls> +</window> \ No newline at end of file Property changes on: trunk/plugins/IPTV@UT/[ Default Skin ]/MyIPTV.xml ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/plugins/MyTorrents/c3o.plugins.suo =================================================================== (Binary files differ) Modified: trunk/plugins/UitzendingGemist/UitGemist.suo =================================================================== (Binary files differ) Modified: trunk/plugins/VideoLAN/ConfigurationForm.cs =================================================================== --- trunk/plugins/VideoLAN/ConfigurationForm.cs 2007-01-31 22:29:16 UTC (rev 69) +++ trunk/plugins/VideoLAN/ConfigurationForm.cs 2007-02-01 00:58:51 UTC (rev 70) @@ -197,7 +197,7 @@ { m_enabledExt = xmlreader.GetValueAsString("vlcplugin", "enabledextensions", ".ts,.gary"); m_enabledStreams = xmlreader.GetValueAsString("vlcplugin", "enabledstreams", "udp"); - bufsize = xmlreader.GetValueAsString("vlcplugin", "buffer", "400"); + bufsize = xmlreader.GetValueAsString("vlcplugin", "buffer", "5000"); m_enabledExt.Replace(":", ","); // in case it was using the old plugin code where the separator was ":" } if (m_enabledExt != null && m_enabledExt.Length > 0) Modified: trunk/plugins/VideoLAN/VideoLanPlugin.cs =================================================================== --- trunk/plugins/VideoLAN/VideoLanPlugin.cs 2007-01-31 22:29:16 UTC (rev 69) +++ trunk/plugins/VideoLAN/VideoLanPlugin.cs 2007-02-01 00:58:51 UTC (rev 70) @@ -30,6 +30,7 @@ bool _isFullScreen = false; bool _notifyPlaying = true; int _positionX = 10, _positionY = 10, _videoWidth = 100, _videoHeight = 100; + int audioDelay = 0; public static VlcUserControl vlcControl = null; @@ -62,7 +63,7 @@ public override string VersionNumber { - get { return "0.6"; } + get { return "0.7"; } } public override string[] GetAllSupportedExtensions() @@ -141,11 +142,24 @@ GUIWindowManager.SendThreadMessage(msg); Player_Initializing(); + string vlciptvdir = Directory.GetCurrentDirectory() + @"\vlciptv"; + if (!Directory.Exists(vlciptvdir)) Directory.CreateDirectory(vlciptvdir); - string[] option = new string[2]; - option[0] = ":http-caching=" + getBufferSize(); - option[1] = ":vout=direct3d"; - + string[] option = new string[]{ + ":http-caching=" + getBufferSize(), + ":mms-caching=" + getBufferSize(), + ":realrtsp-caching=" + getBufferSize(), + //":tcp-caching==" + getBufferSize(), + //":udp-caching==" + getBufferSize(), + ":smb-caching=" + getBufferSize(), + ":snapshot-path=" + vlciptvdir, + ":record-path=" + vlciptvdir, + ":timeshift-dir=" + vlciptvdir, + ":access-filter=record" + }; + + + vlcControl.Stop(); vlcControl.ClearPlayList(); vlcControl.AddToPlayList(strFile, null, option); vlcControl.Play(); @@ -171,16 +185,12 @@ { vlcControl.RotateAudioTrack(); } - if (foAction.wID == Action.ActionType.ACTION_FORWARD) + if (foAction.wID == Action.ActionType.ACTION_TAKE_SCREENSHOT) { - vlcControl.Faster(); + vlcControl.SnapShot(); } - if (foAction.wID == Action.ActionType.ACTION_REWIND) + if (foAction.wID == Action.ActionType.ACTION_RECORD) { - vlcControl.Slower(); - } - if (foAction.wID == Action.ActionType.ACTION_TAKE_SCREENSHOT) - { vlcControl.SnapShot(); } if (foAction.wID == Action.ActionType.ACTION_ASPECT_RATIO) @@ -192,6 +202,87 @@ UpdateStatus(); SetWindows(); } + if (foAction.wID == Action.ActionType.ACTION_AUDIO_DELAY_MIN) + { + if(audioDelay>0) + { + audioDelay--; + vlcControl.AudioDelay = audioDelay; + } + } + if (foAction.wID == Action.ActionType.ACTION_AUDIO_DELAY_PLUS) + { + audioDelay++; + vlcControl.AudioDelay = audioDelay; + } + if (foAction.wID == Action.ActionType.ACTION_BIG_STEP_BACK) + { + vlcControl.BigStepBack(); + } + if (foAction.wID == Action.ActionType.ACTION_BIG_STEP_FORWARD) + { + vlcControl.BigStepForward(); + } + if (foAction.wID == Action.ActionType.ACTION_DVD_MENU) + { + vlcControl.DvdMenu(); + } + //if (foAction.wID == Action.ActionType.ACTION_FORWARD) + //{ + // vlcControl.Faster(); + //} + //if (foAction.wID == Action.ActionType.ACTION_REWIND) + //{ + // vlcControl.Slower(); + //} + if (foAction.wID == Action.ActionType.ACTION_FORWARD || foAction.wID == Action.ActionType.ACTION_STEP_FORWARD) + { + vlcControl.MediumStepForward(); + } + if (foAction.wID == Action.ActionType.ACTION_REWIND || foAction.wID == Action.ActionType.ACTION_STEP_BACK) + { + vlcControl.MediumStepBack(); + } + if (foAction.wID == Action.ActionType.ACTION_MOVE_LEFT) + { + vlcControl.MoveLeft(); + } + if (foAction.wID == Action.ActionType.ACTION_MOVE_RIGHT) + { + vlcControl.MoveRight(); + } + if (foAction.wID == Action.ActionType.ACTION_MOVE_DOWN) + { + vlcControl.MoveDown(); + } + if (foAction.wID == Action.ActionType.ACTION_MOVE_UP) + { + vlcControl.MoveUp(); + } + if (foAction.wID == Action.ActionType.ACTION_NEXT_SUBTITLE) + { + vlcControl.RotateSubtitles(); + } + if (foAction.wID == Action.ActionType.ACTION_NEXT_CHAPTER) + { + vlcControl.NextDvdChapter(); + } + if (foAction.wID == Action.ActionType.ACTION_PREV_CHAPTER) + { + vlcControl.PreviousDvdChapter(); + } + if (foAction.wID == Action.ActionType.ACTION_RECORD) + { + vlcControl.Record(); + } + if (foAction.wID == Action.ActionType.ACTION_SMALL_STEP_BACK) + { + vlcControl.ShortStepBack(); + } + if (foAction.wID == Action.ActionType.ACTION_SELECT_ITEM) + { + vlcControl.Activate(); + } if (foAction.wID == Action.ActionType.ACTION_STOP) { Player_stopEvent(); @@ -565,7 +656,7 @@ private int getBufferSize() { - int result = 400; + int result = 5000; using (MediaPortal.Profile.Settings xmlreader = new MediaPortal.Profile.Settings(Directory.GetCurrentDirectory() + @"\MediaPortal.xml")) { result = xmlreader.GetValueAsInt("vlcplugin", "buffer", 400); Modified: trunk/plugins/VideoLAN/VlcUserControl.cs =================================================================== --- trunk/plugins/VideoLAN/VlcUserControl.cs 2007-01-31 22:29:16 UTC (rev 69) +++ trunk/plugins/VideoLAN/VlcUserControl.cs 2007-02-01 00:58:51 UTC (rev 70) @@ -830,6 +830,11 @@ this.nativeVlc.PressKey("key-snapshot"); } + public void Record() + { + this.nativeVlc.PressKey("key-record"); + } + public void UnCropTop() { //this.nativeVlc.PressKey("key-uncrop-top"); @@ -894,6 +899,11 @@ set { this.useMpegVbrOffset = value; } } + public void DvdMenu() + { + this.nativeVlc.PressKey("key-disc-menu"); + } + public void NextDvdTrack() { this.nativeVlc.PressKey("key-title-next"); @@ -914,6 +924,61 @@ this.nativeVlc.PressKey("key-chapter-prev"); } + public void BigStepBack() + { + this.nativeVlc.PressKey("key-jump-long"); + } + + public void BigStepForward() + { + this.nativeVlc.PressKey("key-jump+long"); + } + + public void MediumStepBack() + { + this.nativeVlc.PressKey("key-jump-medium"); + } + + public void MediumStepForward() + { + this.nativeVlc.PressKey("key-jump+medium"); + } + + public void ShortStepBack() + { + this.nativeVlc.PressKey("key-jump-short"); + } + + public void ShortStepForward() + { + this.nativeVlc.PressKey("key-jump+short"); + } + + public void MoveLeft() + { + this.nativeVlc.PressKey("key-nav-left"); + } + + public void MoveRight() + { + this.nativeVlc.PressKey("key-nav-right"); + } + + public void MoveDown() + { + this.nativeVlc.PressKey("key-nav-down"); + } + + public void MoveUp() + { + this.nativeVlc.PressKey("key-nav-up"); + } + + public void Activate() + { + this.nativeVlc.PressKey("key-nav-activate"); + } + private void VlcUserControl_Resize(object sender, EventArgs e) { if(!ComputeCrop()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |