音频库套件( 用 HTML5/CSS3/jQuery JS/PHP/C#) 制作的完整音频库解决方案

分享于 

101分钟阅读

Web开发

  繁體

观看这里视频演示之前,请先观看:让我们看

下载最新版本的音频库套件从 GITHUB。 ( 在github上,这个 repo 花费了的费用)

更新了( 30 -april-2013 ) - Audio-Gallery-Suite现在已经有了一个基于web的管理接口,该接口为名为的音频库提供了一个基于web的管理接口。 Gallardmin提供了复杂易用的全功能管理接口。 它使用了最新 xhr2.html5和javascript技术的强大功能。

更新的( 02 -july-2012 ) - Audio-Gallery-Suite已经更新,并且现在与IE9兼容。

索引

描述

收费是一个完整的音频库套件/解决方案,包括一个网络音频库和管理播放列表,上传音频以及管理网络音频库的软件。 使用最新技术构建 Audio-Gallery-Suite,并利用它们的力量来构建一个复杂的解决方案。 Audio-Gallery-Suite是由任何希望使用它的人轻松设置和部署的。 我希望这个项目对任何打算使用它的人都是有用的。

技术

  • HTML5
  • CSS3
  • javascript/jquery
  • AJAX
  • PHP
  • MySQL
  • .NET/C#

演示

查看给定 below 链接的网络音频库。 我建议 Chrome/Firefox 网络浏览器查看网络音频库。 http://projects.robinrizvi.info/audio-gallery-suite/

下载 below 链接的链接,上传音频和管理这个演示中使用的网络音频库。 使用用户名 [superuser] 和密码 [superuser] 不使用方括号登录软件。
http://projects.robinrizvi.info/audio-gallery-suite/software/audiogallery_setup.zip

下载/捐赠

下载完整的Audio-Gallery-Suite以及Audio-Gallery-Suite中使用的完整源代码和所有资源。 如果你想在任何项目中实现 Audio-Gallery-Suite,你必须下载整个套件,并按照我稍后讨论的设置指导进行操作。 你可以提供这个项目并使它的更好,并且可以通过使用 below的相同链接在GitHub上分叉项目。
https://github.com/robinrizvi/Audio-Gallery-Suite

特性

网络图库
  • 播放列表的动态加载。
  • 属于播放列表的音频的动态加载
  • 动态音频搜索
  • 轻松使用音频播放器
  • 可以选择播放。暂停。下一步。前一个。音量控制和查找选项
  • 音频播放器可以使用键盘按键操作
  • 指示音频播放状态的旋转盘。
  • 音频共享到流行的社交网络
  • 当前选择的音频可以下载
  • 可以看到和复制到音频文件的直接链接
  • 流体布局,当浏览器调整大小时,网络库调整自身
图库软件
  • 播放列表可以添加,编辑和删除
  • 音频可以添加到任何已经添加的播放列表中
  • 可以编辑和删除音频
  • 可以配置更改用户名和密码等设置
  • 其他用户可以添加,编辑和删除( 仅通过超级用户帐户)
  • 响应/非阻塞用户界面
  • 上传音频的过程显示
  • 上传前,要上传的每个音频都有一个标签( 也叫专辑艺术) 标签

( 使用 Gallardmin - web库管理软件)

  • 下载: https://github.com/robinrizvi/Audio-Gallery-Suite/archive/master.zip
  • 在你的mysql服务器中执行以下sql脚本 ( 在资源/sql脚本中出现) : 1 ) audiogallery_db.sql 2 ) create_user_ [optional]。 sql查询
  • 如果数据库或者数据库用户所做的任何更改,而不是由上述sql脚本执行的默认数据库或者数据库用户更改,则为
  • 将库文件夹的内容从zip复制到你的服务器。
  • 转到 http://root_url_to_gallery_folder/management/audiogallery/login.html
  • 分别以用户名和密码为用户输入超级用户和超级用户。
  • 添加播放列表并在播放列表下添加音频。
  • 转到 http://root_url_to_gallery_folder/index.html 查看你的图片库

安装( 使用基于的管理软件在远程服务器上)

便笺
  • 方括号 [] 只是用来指示重要的,否则应该忽略它们。
  • [root_url_of_web_gallery] 指web站点的文件或者 url,web gallery的文件将存放在其中。 示例:在我的演示( 请参见演示部分 上面 ) 中,它是 http://projects.robinrizvi.info/audio-gallery-suite/ (http://www.yourdomain.com/foldername/).
初始步骤
  • 从GitHub下载完整的Audio-Gallery-Suite。 解压下载的zip文件的内容。
  • 现在你必须有一个包含audio-gallery-suite的文件夹,其中包含你的磁盘中的服务器。
  • 在磁盘上打开 [Audio-Gallery-SuiteGallery] 文件夹,并在其中创建一个文件夹为 [audiogallery]的文件夹。
  • 现在打开 [Audio-Gallery-SuiteGalleryaudiogallery] 文件夹,并在其中创建一个 [user_0]。 你的磁盘上应该有的[Audio-Gallery-SuiteGalleryaudiogalleryuser_0]
上传网页:
  • 从磁盘 [Audio-Gallery-SuiteGallery] 文件夹中的所有文件到 [root_url_of_web_gallery] ( 请参见"注释"上方上方) 中的服务器/主机。
配置 FTP:
  • 在服务器/主机上创建一个FTP帐户,该帐户指向服务器上的 [root_url_of_web_gallery/audiogallery] 目录。 请记住我们将使用( FTP服务器,FTP用户名,FTP密码),所以请记下它们。
创建数据库:
  • 从磁盘中打开 [Audio-Gallery-SuiteResourcesSQL Script] 文件夹中的[audiogallery_db.sql] ( 你可以在记事本等文本编辑器中打开sql文件)。
  • 如果希望将数据库名称从默认名称 [audiogallery] 更改为其他名称,则为0,可以通过将行 [CREATE DATABASE if not EXISTS audiogallery;USE audiogallery;] 更改为 [CREATE DATABASE if not EXISTS some_other_database_name;USE some_other_database_name; ] 来完成。
  • 如果已经用其他名称创建数据库,请按以下步骤操作:从sql脚本中删除行,并编辑行 [USE audiogallery],如下面的[USE your_other_db_name;]。
  • 如果要更改超级用户和密码的用户名,则可以从 [audiogallery_db.sql] 更改为: [ 插入 `user` (。`id`,`username`,`password`,`name`,`description` ) 值
    ( 0,'your_superuser_username','your_superuser_password','超级用户','创建和管理其他用户并可以创建并管理自己的播放列表和音频的超级用户') ;]。
  • 在文件中按如下方式更改ftp设置的值: [ 插入 `settings` ( `ftpurl`,`ftpusername`,`ftppassword` ) 值 ('ftp://your_ftp_server/','ftp_username','ftp_password');]. 记住这三个值是在服务器( 请参见"配置 FTP"节 上面 ) 上创建FTP帐户时获得的值。
  • 在保存和执行文件之前,请确保超级用户配置和ftp配置正确设置了。
  • 保存 [audiogallery_db.sql] 文件。
  • 执行 上面 更改后,执行 你可以通过使用服务器的PHPMYADMIN执行sql脚本,或者下载 MySQL Workbench ( 下载链接 ) 并连接到远程数据库服务器,然后导入sql脚本,然后执行它。
  • 记住我们需要记下数据库 NAME的a 用户的用户名和密码( 我们创建的数据库中的数据库(。例如 授权执行操作的用户( 运行查询) )
配置 PHP:
  • 从磁盘上的[Audio-Gallery-SuiteGalleryphp] 文件夹中打开 [config.php] 文件 你可以在任何文本编辑器中打开这里文件。
  • 在中按如下方式配置数据库设置的费用: [$mysqli = new mysqli("localhost","DB_USERNAME","DB_PASSWORD","DB_NAME"); ]。请记住,不需要更改 [localhost],它的余三个值是创建数据库时在服务器( 请参见"创建数据库"节 上面 )的值。
  • 在 [config.php] 文件中配置 [$root] 变量的如下所示: [$root="http://root_url_of_web_gallery/";]. what is [root_url_of_web_gallery]( 请参见"注释"节 上面 )。 示例:[$host="http://projects.robinrizvi.info/audio-gallery-suite/"] 在我的演示( 请参见演示部分 上面 ) 中使用。 记住不要忘了把后面的正斜杠放在末尾。
  • 在执行 上面 更改后保存 [config.php] 文件
  • 在 [config.php] 文件夹中将文件从磁盘上的[Audio-Gallery-Suite/Gallery/php] 文件夹上载到 [root_url_of_web_gallery/php] 文件夹( 替换旧的[config.php] 文件) 中的服务器/主机
配置网络图库软件:
  • 从磁盘上的文件夹中打开 [AUDIO GALLERY.sln] 文件
  • 从audiogallery项目中打开资源( 来自 Solution-Explorer-> Properties-> 资源)的
  • 从资源中编辑 [mysqlconnectionstring] 设置以正确配置Mysql数据库连接设置:如下: 记住,DB_SERVER将会像 server=your_host_domain.com 一样引用服务器( 数据库服务器运行的例如 ),剩下的3 ( DB_USERNAME,DB_NAME,DB_PASSWORD ) 将是我们创建数据库( 请参见"数据库"节 上面 ) 时记录下来的。
  • 重新生成整个解决方案
添加一些播放列表和音频:
  • 现在运行 ( 从构建exe或者从或者从 audiogallery_setup.exe )
  • 使用超级用户和密码 ( 默认值为 [superuser] 和 [superuser] )的用户名进行
  • 在这里你可以创建一些播放列表,并向他们添加音频,这样网络画廊就能显示一些音频。
  • Wipe and see,see working

安装( 在本地服务器/本地主机使用 Windows的管理软件收费)

注:
  • 方括号 [] 只是用来指示重要的,否则应该忽略它们。
  • [root_url_of_web_gallery] 指测试本地服务器的url,其中网络库的文件将驻留在本地服务器上。 示例:本地设置 [gallery]的http://localhost/gallery/, 是我在我的计算机的[apache webserver] (。[http://localhost] 是 url ( 环回)的[www] 文件夹中创建的文件夹,该文件夹指向 [www] 文件夹)。
  • [root_folder_of_web_gallery] refers指测试本地服务器中的文件夹,该文件夹的文件将驻留在本地服务器上。 在我的本地设置 http://localhost 中,会指向 [C:Program Files (x86)EasyPHP- 5.3.6.1 www] 文件夹,然后我创建一个名为gallery的文件夹,所以我的[root_folder_of_web_gallery] 是 [C:Program Files (x86)EasyPHP- 5.3.6.1 wwwgallery],我的[root_url_of_web_gallery] 是
初始步骤:
  • 从GitHub下载完整的Audio-Gallery-Suite。 解压下载的zip文件的内容。
  • 现在你必须有一个包含audio-gallery-suite的文件夹,其中包含你的磁盘中的服务器。
  • 在磁盘上打开的[Audio-Gallery-SuiteGallery] 文件夹,并在其中创建一个文件夹
  • 现在打开 [Audio-Gallery-SuiteGalleryaudiogallery] 文件夹,并在其中创建一个 [user_0]。 你的磁盘上应该有的[Audio-Gallery-SuiteGalleryaudiogalleryuser_0]
  • 你必须在本地计算机上安装 ( Windows+Apache+MySQL+PHP ) stack。 如果还没有,可以从下载链接下载。 记住你也可以选择 LAMP 栈,但为了运行. NET 软件,推荐你使用 WAMP。
  • 计算机上必须有本地FTP服务器。 你可以使用IIS或者 Xlight ftp服务器 ( 请参见 Xlight用法指南。)。
上传网页:
  • 从磁盘 [Audio-Gallery-SuiteGallery] 文件夹中的所有文件复制到 [root_folder_of_web_gallery] 文件夹( 请参见"便笺"上方上方) 服务器的本地站点文件夹 to。 示例- 我将所有文件复制到这里文件夹 [C:Program Files (x86)EasyPHP- 5.3.6.1 wwwgallery ]
配置 FTP:
  • 使用(。Xlight - 请参见 Xlight用法说明或者 IIS ) 在本地计算机上添加一个FTP站点,它指向服务器上的 [root_folder_of_web_galleryaudiogallery] 目录。 请记住我们将使用( FTP服务器,FTP用户名,FTP密码),所以请记下它们。 我的FTP服务器是 localhost,FTP用户名是 robinr,FTP密码是,FTP站点指向 [C:Program Files (x86)EasyPHP- 5.3.6.1 wwwgalleryaudiogallery] 文件夹
创建数据库:
  • 以为单位打开磁盘中的 [Audio-Gallery-SuiteResourcesSQL Script] folder。 ( 你可以在记事本等文本编辑器中打开sql文件)。
  • 如果希望将数据库名称从默认名称 [audiogallery] 更改为其他名称,则为0,可以通过将行 [CREATE DATABASE if not EXISTS audiogallery;USE audiogallery;] 更改为 [CREATE DATABASE if not EXISTS some_other_database_name;USE some_other_database_name; ] 来完成。
  • 如果已经用其他名称创建数据库,请按以下步骤操作:从sql脚本中删除行,并编辑行 [USE audiogallery],如下面的[USE your_other_db_name;]。
  • 如果要更改超级用户和密码的用户名,则可以从 [audiogallery_db.sql] 更改为: [ 插入 `user` (。`id`,`username`,`password`,`name`,`description` ) 值
    ( 0,'your_superuser_username','your_superuser_password','超级用户','创建和管理其他用户并可以创建并管理自己的播放列表和音频的超级用户') ;]。
  • 在文件中按如下方式更改ftp设置的值: [ 插入 `settings` ( `ftpurl`,`ftpusername`,`ftppassword` ) 值 ('ftp://your_local_ftp_server_url/','ftp_username','ftp_password');]. 记住这三个值是在服务器( 请参见"配置 FTP"节 上面 ) 上创建FTP帐户时获得的值。 示例-'ftp://localhost/','罗宾','robinr'是我的三个值。
  • 在保存和执行文件之前,请确保超级用户配置和ftp配置正确设置了。
  • 保存 [audiogallery_db.sql] 文件。
  • 执行 上面 更改后,执行 你可以通过使用本地服务器的PHPMYADMIN执行sql脚本,或者下载 MySQL Workbench ( 下载链接 ) 并连接到本地数据库服务器,然后导入sql脚本并执行它。
  • 记住我们需要记下数据库 NAME的a 用户的用户名和密码( 我们创建的数据库中的数据库(。例如 授权执行操作的用户( 运行查询) )。 如果你在计算用户的用户名密码时遇到任何问题,我们刚刚创建了你可以更改/配置并执行 [create_user_[optional]。 在 [Audio-Gallery-SuiteResourcesSQL Script] 文件夹中找到 sql] sql脚本。
配置 PHP:
  • 从 [root_folder_of_web_galleryphp] 文件夹中打开 [config.php] 文件 你可以在任何文本编辑器中打开这里文件。 示例- 本地安装程序中的config.php 文件驻留在 [C:Program Files (x86)EasyPHP- 5.3.6.1 wwwgalleryphpconfig.php ] 中
  • 在中按如下方式配置数据库设置的费用: [$mysqli = new mysqli("localhost","DB_USERNAME","DB_PASSWORD","DB_NAME"); ]。请记住,不需要更改 [localhost],它的余三个值是创建数据库时在服务器( 请参见"创建数据库"节 上面 )的值。 示例- [$mysqli = new mysqli("localhost","audgaldbusr","audgaldbpwd","audiogallery");] 在本地设置中使用。
  • 在 [config.php] 文件中配置 [$root] 变量的如下所示: [$root="http://root_url_of_web_gallery/";]. what is [root_url_of_web_gallery]( 请参见"注释"节 上面 )。 示例:[ $host="http://localhost/gallery/";] 在本地设置中使用。 记住不要忘了把后面的正斜杠放在末尾。
  • 在执行 上面 更改后保存 [config.php] 文件
配置网络图库软件:
  • 从磁盘上的文件夹中打开 [AUDIO GALLERY.sln] 文件
  • 从audiogallery项目中打开资源( 来自 Solution-Explorer-> Properties-> 资源)的
  • 从资源中编辑 [mysqlconnectionstring] 设置以正确配置Mysql数据库连接设置:如下: [server=DB_SERVER_HOST;User Id=DB_USERNAME;Persist Security Info=True;database=DB_NAME;password=DB_PASSWORD]。示例- [server=localhost;User Id=audgaldbusr;Persist Security Info=True;database=audiogallery;password=audgaldbpwd],这是我在本地设置中使用的设置。 记住DB_SERVER将引用你的本地主机/服务器( 数据库服务器运行的例如 ),它的余三个( DB_USERNAME,DB_NAME,DB_PASSWORD ) 将是我们创建数据库( 请参见"创建数据库"节 上面 )的时候。
  • 重新生成整个解决方案
添加一些播放列表和音频:
  • 现在运行 ( 从构建exe或者从或者从 audiogallery_setup.exe )
  • 使用超级用户和密码 ( 默认值为 [superuser] 和 [superuser] )的用户名进行
  • 在这里你可以创建一些播放列表,并向他们添加音频,这样网络画廊就能显示一些音频。
  • 快乐 !

对代码的深入了解

我将介绍audio-gallery-suite如何工作( 简短)的内部工作原理。 在深入了解代码和内部工作原理之前,建议你查看演示部分( 查看 上面 )。 我将讨论 audio-gallery-suite ( web图片库和图片库软件) 一些关键特性的实现,并对实现这些功能的代码作一个简要的了解。

注释: 代码的重要部分以粗体斜体标记。

使用指导

在获取代码之前,让我们先来看看整个代码是如何工作的。 让我们来了解一下套件主要部分的抽象概念,以及它们如何组合在一起。 套房的主要部件是:

  • 将音频上传到的服务器/主机上的[audiogallery] 目录
  • 对包含音频。播放列表。用户和套件使用的常规设置的详细信息的数据库
  • 向网站用户提供展示网站音频的网络音频库的
  • 将授权用户用于创建播放列表和上传音频的音频库软件收费。
  • 333670/suite_comp_bonding.jpg

让我们考虑一个场景来理解audio-gallery-suite如何工作,上面提到的四个部分如何在( 神奇的是我希望) 中组合在一起。

  • 使用超级用户用户名/密码在音频库软件中输入 超级用户帐户是最初存在的默认帐户。
  • 点击 [Manage Users] 按钮。
  • 创建用户帐户 [user_test] ( 请注意: 只有超级用户才能创建用户)
  • 创建用户 [user_test] 后,向 [user] table 输入一个记录,然后为该用户创建一个自动 [id]。
  • 服务器/主机上的[audiogallery] 目录现在看起来如下所示: {Root}/audiogallery/user_2
  • 现在,用 [user_test] 帐户向gallery软件中添加
  • 然后通过单击播放列表窗格中的按钮创建播放列表 [playlist_test]。
  • 在播放播放时,将在 [playlist] 表中添加播放列表条目,并将自动 [id] 作为playlist表的用户 例如 [user_id=2] 指定用户 [user_test] 作为它的用户。
  • 服务器/主机上的[audiogallery] 目录如下所示: {Root}/audiogallery/user_2/playlist_1/audios
  • 现在点击软件中的这个 [playlist_test] 使它的成为当前播放列表。
  • 接下来,使用音频面板中的按钮为 [playlist_test] 添加一些音频。
  • 在添加音频时,记录会添加到数据库中的[audio] table 中。 通过在记录中指定正确的[playlist_id] 来指定 [audio] 表的每个记录,在我们的例子中,新添加的音频将被显示为 [playlist_id=1]。
  • 添加的音频将像这样上传到这里目录: {Root}/audiogallery/user_2/playlist_1/audios/audio_test.mp3
  • 现在在打开 web gallery 加载页面/dom之后,通过查询数据库中的[playlist] 表,将收费的播放列表加载到下拉列表中。
  • 现在,当你从web图库的下拉列表中选择你的播放列表 [playlist_test] 时,通过查询数据库中的[audio] 表,将加载属于 [playlist_test]的的音频。
  • 选择 [playlist_test] 播放列表后,你将在网站库中的中看到 [audio_test]/mp3文件 ( 你可能已经在 [playlist_test] 播放列表下上传的任何其他文件)。
  • 现在只需点击web网站的[audio_test] ,欣赏一些悦耳的音乐

观看下面的视频以清楚了解上面讨论的场景。

在 Youtube 上观看收费的

至此,我们再走几个步骤。 正如 上面 所提到的,Audio-Gallery-Suite的四个主要部分是: [audiogallery] 目录,数据库,网络音频库和音频库软件。 这四个主要部分的在 below ( 在所述序列中) 中更详细地讨论。

1目录结构

让我们看一下音频将被上传的目录的结构。 这里目录名为 [audiogallery]。 由于这里目录包含播放列表和上传的音频,并且它使用的是音频库软件和web音频库。 它具有特定的目录结构格式,如下所示: %7BRoot%7D/audiogallery/user_id/playlist_id/audios/

333670/5qxmc_New-Sheet.jpg

2数据库结构

333670/audiogallery_db_dig.jpg

上面 图表中显示的数据库模式显示了数据库中使用的四个表。

  • 音频: 音频 table 包含上传的音频。 它指定了音频的id。NAME。标题和描述。 它有一个属性 [playlist_id],它指定特定音频所属的播放列表。
  • 播放列表: 播放列表 table 包含创建的paylists。 它指定了 id,NAME,thumb ( 代表播放列表的缩略图) 和播放列表的描述。 它有一个属性 [user_id] 指定了创建特定播放列表的用户,并拥有管理该播放列表的权限。
  • 用户: 用户 table 包含所有授权使用音频库软件的用户。 它指定了 id。用户名。密码。NAME 和特定用户的描述。 授权用户可以创建播放列表并上传音频。 用户上传的音频将属于他创建的播放列表之一。
  • 设置: 设置 table 只包含关于FTP信息的单个记录。 这里FTP信息由音频库软件用于将音频上载到服务器/主机。

3网页库

HTML骨架 333670/cu29_New-Sheet.jpg

web gallery的主要文件是 [index.html] 文件。 它的结构如 上面 图所示。 视觉上,它分为两部分,左边和右边是两个部分。 ( 请参阅屏幕部分 below 以获得更详细

左部分包含播放列表选择元素。音频 List 和音频搜索元素。

正确的部分包含 coverart ( DVD盒),音频播放器,当前播放音频名和播放列表名称。

下面是显示主要 [index.html ]的屏幕截图

333670/scr1.jpg

可以看到原始HTML代码和 [ index.html ] 结构。

HTML代码
<body><!--Contains the album selector, audios from the playlist and search--><divid="left"><divid="playlistselecttoolbar"><label>Select Playlist :</label><selectname="playlistselect"id="playlistselect"><!--Content will be loaded via ajax php from the database--></select></div> 
 <divid="audiolist"> 
 <!--Content will be loaded via ajax php from the database.--></div><divid="searchaudiotoolbar"><label>Search Audio :</label><inputid="searchinput"name="audiosearchtxt"type=
"text"/><divid="searchbtnimg"></div></div></div> 
 <!--Contains the audio player, cover art and hopefully a visualizer if I can pull it off--><divid="right"><divid="coverart"><imgsrc="image/audiogallery_images/coverart.png"oriwidth="693"oriheight="680"width="693"height="680"alt="coverart"/><imgid="rotatingdisc"src="image/audiogallery_images/rotating_disc.png"width="350"height="350"alt="rotatingdisc"name="rotatingdisc"/></div> 
 <divclass="sharebar"><inputname="audiourl"type="text"readonly="true"/> 
 <!--<a id="copyurltool" class="button gray medium">COPY</a>--></div><divid="toolbar"><aid="shareaudiotool"class="sharebar-trigger button gray medium"name="shareaudiotool">LINK</a> 
 <aid="addthissharetool"class="sharebar-trigger button gray medium"name="addthissharetool">SHARE</a> 
 <aid="downloadaudiotool"target="_blank"class="button gray medium"name="downloadaudiotool">DOWNLOAD</a> 
 <aid="helptool"class="button gray medium"rel="prettyPhoto[inline]"href="#inline_content"name="helptool">HELP</a></div><divid="player"><divid="jquery_jplayer_2"class="jp-jplayer"></div><divclass="jp-audio"><divclass="jp-type-playlist"><divid="jp_interface_2"class="jp-interface"><ulclass="jp-controls"><li><ahref="#"class="jp-play"tabindex="1">play</a></li><li><ahref="#"class="jp-pause"tabindex="1">pause</a></li><li><ahref="#"class="jp-stop"tabindex="1">stop</a></li><li><ahref="#"class="jp-mute"tabindex="1">mute</a></li><li><ahref="#"class="jp-unmute"tabindex="1">unmute</a></li><li><ahref="#"class="jp-previous"tabindex="1">previous</a></li><li><ahref="#"class="jp-next"tabindex="1">next</a></li></ul><divclass="jp-progress"><divclass="jp-seek-bar"><divclass="jp-play-bar"></div></div></div><divclass="jp-volume-bar"><divclass="jp-volume-bar-value"></div></div><divclass="jp-current-time"></div><divclass="jp-duration"></div></div></div></div></div><divid="playerstatbar"><spanid="nowplaying">Now Playing:</span><spanid="currentplaylist">Current
 Playlist: </span></div></div><!--This is an isolated div to show help to the users--><divstyle='display:none'><divid='inline_content'><divstyle="background-color:#000;padding:5px;width:98%; 
 margin-bottom:5px;text-align:center;color:#FFF;height:1em;font-size:1em;"> HELP/INSTRUCTIONS
 </div><divstyle='padding:10px; vertical-align:middle; font-size:0.9em;'><divstyle="margin-bottom:15px"><imgstyle='vertical-align:middle;'src="image/help_images/mouse.png"width=
"50"height="70"/><spanstyle='margin-left:10px;'>Use your mouse 
 to interact with the player.</span></div><divstyle="margin-bottom:15px"><imgstyle='vertical-align:middle;'src="image/help_images/space.png"width=
"150"height="50"/><spanstyle='margin-left:10px;'>Press the space-bar to
 toggle Play and Pause.</span></div><divstyle="margin-bottom:15px"><imgstyle='vertical-align:middle;'src="image/help_images/right.png"width=
"50"height="50"/><spanstyle='margin-left:10px;'>Press the right arrow key to
 jump to next audio.</span></div><divstyle="margin-bottom:15px"><imgstyle='vertical-align:middle;'src="image/help_images/left.png"width="50"height="50"/><spanstyle='margin-left:10px;'>Press the left arrow key to jump
 to previous audio.</span></div><divstyle="margin-bottom:15px"><imgstyle='vertical-align:middle;'src="image/help_images/m.png"width="50"height="50"/><spanstyle='margin-left:10px;'>Press the M key to toggle mute
 and unmute.</span></div><divstyle="margin-bottom:15px"><imgstyle='vertical-align:middle;'src="image/help_images/shift.png"width=
"50"height="50"/> + <imgstyle='vertical-align:middle;'src=
"image/help_images/right.png"width="50"height="50"/><spanstyle=
 'margin-left:10px;'>Use Shift + Right arrow key to seek forward.</span></div><divstyle="margin-bottom:15px"><imgstyle='vertical-align:middle;'src="image/help_images/shift.png"width=
"50"height="50"/> + <imgstyle='vertical-align:middle;'src=
"image/help_images/left.png"width="50"height="50"/><spanstyle=
 'margin-left:10px;'>Use Shift + Left arrow key to seek backward.</span></div></div><divstyle="background-color:#000;padding:5px;width:98%; 
 margin-bottom:5px;text-align:center;color:#FFF;height:1em;font-size:1em;"><inputname="popupstartup"id="popupstartupcheck"onchange="showpopupchange();"type="checkbox"value=""/> Do not show at start up!
 </div></div></div></body>

[index.html]

在看到基本框架和HTML之后,让我们继续看看网络音频库的基本特性和功能,以及它们是如何实现的。

加载播放列表

DOM在 $(document).ready(function(){---}) 中准备好 例如,在使用数据( playlistselct: 1 )的时候,将对的AJAX请求进行收费。 接收到数据后,[audiogalleryengine.php] 数据库为所有播放列表查询数据库每个播放列表记录option选项> 元素。

在载入播放列表后,让我们看看屏幕截图:

333670/playlist_loading.jpg

现在让我们看一下不同文件的代码,使之发生:

<selectname="playlistselect"id="playlistselect"><!--Content will be loaded via ajax php from the database--></select>

[index.html]

//Filling the playlist select box with values via XHR/ajax$("#playlistselect").load("php/audiogalleryengine.php",{playlistselect:1},
 function(){$("#playlistselect").change();$('select').selectmenu({style:'dropdown'});}); 

[script_audio.js]

//for getting all the playlist and returning themif (isset($_POST['playlistselect']))
{
 $query="SELECT * FROM playlist";
 $result=$mysqli->query($query);
 $responsehtml='<option value="0">All</option>';
 while($tuple=$result->fetch_array())
 {
 $responsehtml.="<option value={$tuple['id']}>{$tuple['name']}</option>"; }
 $result->close();
 echo $responsehtml;
 exit();
}

[audiogalleryengine.php]

加载音频

当播放列表更改或者用户进行音频搜索时,会加载音频。 根据播放列表选择 box(dropdown) 和搜索文本的值,使用数据( playlistid和 searchtext ) 对 [ audiogalleryengine.php ] 进行一个AJAX调用。 根据接收到的数据,[ audiogalleryengine.php ] 查询数据库( 音频 table ),查找属于特定播放列表的所有音频,以及与搜索文本相似的内容。 从数据库接收到音频记录后,[ audiogalleryengine.php ] 表单 <li> 所有音频的元素。

在载入音频后,让我们看看屏幕截图:

333670/audio_list.jpg

现在让我们看一下不同文件的代码,使之发生:

<divid="audiolist"><!--Content will be loaded via ajax php from the database.--></div>

[index.html]

//Event handler for playlistselect change$("#playlistselect").change(function(){
 searchaudio();
 $("#currentplaylist span").text($("#playlistselect :selected").text());
}); //Initializing the audio search button$("#searchbtnimg").click(function(){
 searchaudio();
});//Calling search audio function each time when user presses a key$("#searchinput").keyup(function(){ 
 searchaudio();
});functionsearchaudio()
{
 searchxhrabort();
 $("#audiolist").showLoading();
 window.searchxhr = $.ajax({
 type: "POST",
 url: "php/audiogalleryengine.php",
 data: "playlistid="+$('#playlistselect').val()+
 "&searchtext="+$('#searchinput').val(),
 success: function(html){
 //Adding the ajax returned audiotracks to the audiolist and reinitializing jscrollpane window.scrollableaudiolist.html(html);
 window.jscrollapi.reinitialise();
 $("#audiolist").hideLoading();
 //Storing previous currentplaytime beforing creating a new playlist from//the new search items because after creating the new playlist the//currentplaytime would automatically get to zero so that I can//seek properly if the old element is found in the new search $("#player").data("previouscurrenttime",
 $("#player").data("currenttime"));
 //Reinitializing the playlist for jplayer createplaylist();//Checking if the current playing track in the old playlist is also//present in the new search list and taking actions accordinglyvar trackidifany=currenttrackinnewsearch();
 if (trackidifany===false)
 {
 window.audioPlaylist.playlistChange(0);
 $("#jquery_jplayer_2").jPlayer("stop");
 }
 else {
 window.audioPlaylist.playlistChange(trackidifany);
 $("#jquery_jplayer_2").jPlayer(
 "pause",$("#player").data("previouscurrenttime")); 
 } 
 //Adding event hander for the newly loaded audiotracks $(".audiotrack").click(function(){
 var audiotrackindex=$(this).index();
 window.audioPlaylist.playlistChange(audiotrackindex);
 });
 }
 });
}

[script_audio.js]

if (isset($_POST['playlistid']) && isset($_POST['searchtext']))
{
 $playlistid=$_POST['playlistid'];
 $searchtext=$_POST['searchtext'];
 if ($searchtext=="") $searchtext="%"; 
 else $searchtext="%".$searchtext."%";
 if ($playlistid==0)
 $query="SELECT audio.name AS name,audio.title AS title,audio.playlist_id 
 AS playlistid,playlist.user_id AS userid FROM (audio JOIN playlist 
 ON audio.playlist_id=playlist.id) WHERE audio.title LIKE '{$searchtext}'";
 else $query="SELECT audio.name AS name,audio.title AS title,
 audio.playlist_id AS playlistid,playlist.user_id AS userid FROM 
 (audio JOIN playlist ON audio.playlist_id=playlist.id) WHERE 
 audio.playlist_id={$playlistid} AND audio.title LIKE '{$searchtext}'";
 $result=$mysqli->query($query);
 $html="<ul>";
 while($tuple=$result->fetch_array())
 {
 $userid=$tuple['userid'];
 $playlistid=$tuple['playlistid'];
 $name=$tuple['name'];
 $title=$tuple['title'];
 $audiourl="{$root}audiogallery/user_{$userid}/playlist_{$playlistid}/audios/{$name}";
 $html.="<li class="audiotrack" 
 url="{$audiourl}">{$title}</li>";  
 }
 $html.="</ul>";
 echo $html;
}

[audiogalleryengine.php]

> 初始化播放列表

audio-gallery-suite中的音频播放器使用Jplayer播放和维护播放列表信息。 不过有一点很简单,那是( 或者只为) static 播放列表的文档,所以我不得不用一些技巧把播放列表数据给jplayer函数播放列表,这样一切都正常运行。 我创建了一个类似这样的对象字符串: myaudioplaylist= [{name:"title",mp3:"url"},{..},.. 在创建名为myaudioplaylist的对象上创建了 eval() javascript函数,并将它传递到Jplayer播放列表构造函数。 了解清楚理解代码。 所有这些功能都封装到一个 createplaylist() 函数中,当用户从播放列表选择下拉列表中选择一。

现在让我们看一下不同文件的代码,使之发生:

function createplaylist()
{
 var objectarraystring="var myaudioplaylist=[";
 $(".audiotrack").each(function(){
 objectarraystring=objectarraystring+"{name:""+$(this).text()+
 "",mp3:""+$(this).attr('url')+""},";
 });
 objectarraystring+="]";
 eval(objectarraystring); audioPlaylist = new window.Playlist("2",
 myaudioplaylist, {
 ready: function() {
 audioPlaylist.playlistInit(false); // Parameter is a boolean for autoplay. },
 ended: function() {
 audioPlaylist.playlistNext();
 },
 play: function() {
 $(this).jPlayer("pauseOthers");
 },
 swfPath: "flash",
 supplied: "mp3",
 solution: "html, flash",
 wmode: "window",
 preload: "auto"});
}

[script_audio.js]

> 播放音频/初始化 Jplayer

音频通过 Jplayer ( 一个Jquery插件) 播放和控制,因此它是使用Jplayer标准/技术实现的。 请访问 http://jplayer.org/ 了解详情。

让我们看一下web图库中( 自定义) Jplayer界面的屏幕截图:

333670/jplayer.jpg

现在让我们看一下不同文件的代码,使之发生:

<div id="player">
 <div id="jquery_jplayer_2" class="jp-jplayer"></div>
 <div class="jp-audio">
 <div class="jp-type-playlist">
 <div id="jp_interface_2" class="jp-interface">
 <ul class="jp-controls">
 <li><a href="#" class="jp-play" 
 tabindex="1">play</a></li>
 <li><a href="#" class="jp-pause" 
 tabindex="1">pause</a></li>
 <li><a href="#" class="jp-stop" 
 tabindex="1">stop</a></li>
 <li><a href="#" class="jp-mute" 
 tabindex="1">mute</a></li>
 <li><a href="#" class="jp-unmute" 
 tabindex="1">unmute</a></li>
 <li><a href="#" class="jp-previous" 
 tabindex="1">previous</a></li>
 <li><a href="#" class="jp-next" 
 tabindex="1">next</a></li>
 </ul>
 <div class="jp-progress">
 <div class="jp-seek-bar">
 <div class="jp-play-bar"></div>
 </div>
 </div>
 <div class="jp-volume-bar">
 <div class="jp-volume-bar-value"></div>
 </div>
 <div class="jp-current-time"></div>
 <div class="jp-duration"></div>
 </div>
 </div>
 </div>
</div>

[index.html]

$(document).ready(function(){
//Other code here see source files, removed it for a clearer view
//Global variables for playlist management
var Playlist;
var audioPlaylist;/*Defines Jplayer Playlist Class*/
initjplayerplaylistfunctions();});
function initjplayerplaylistfunctions()
{
 Playlist = function(instance, playlist, options) {
 var self = this;
 this.instance = instance;//String: To associate specific HTML with this playlist
 this.playlist = playlist;//Array of Objects: The playlist
 this.options = options;//Object: The jPlayer constructor options for this playlist
 this.current = 0;
 this.cssId = {
 jPlayer:"jquery_jplayer_",
 interface:"jp_interface_",
 playlist:"jp_playlist_"
 };
 this.cssSelector = {};
 $.each(this.cssId, function(entity, id) {
 self.cssSelector[entity] ="#" + id + self.instance;
 });
 if(!this.options.cssSelectorAncestor) {
 this.options.cssSelectorAncestor = this.cssSelector.interface;
 }
 $(this.cssSelector.jPlayer).jPlayer(this.options);
 $(this.cssSelector.interface +". jp-previous").click(function() {
 self.playlistPrev();
 $(this).blur();
 return false;
 });
 $(this.cssSelector.interface +". jp-next").click(function() {
 self.playlistNext();
 $(this).blur();
 return false;
 });
 };
 Playlist.prototype = {
 playlistInit: function(autoplay) {
 if(autoplay) {
 this.playlistChange(this.current);
 } else {
 this.playlistConfig(this.current);
 }
 },
 playlistConfig: function(index) {
 $(this.cssSelector.playlist +"_item_" + this.current).removeClass(
"jp-playlist-current").parent().removeClass("jp-playlist-current");
 $(this.cssSelector.playlist +"_item_" + index).addClass(
"jp-playlist-current").parent().addClass("jp-playlist-current");
 this.current = index;
 $(this.cssSelector.jPlayer).jPlayer("setMedia", this.playlist[this.current]);
 $("#nowplaying span").text(this.playlist[this.current].name);
 $("#player").data("currenttrackurl",this.playlist[this.current].mp3);
 playlistuiupdate(1,$('#player').data("currenttrackindex"),index);
 $('#player').data("currenttrackindex",index);
 shareupdate($("#player").data("currenttrackurl"),this.playlist[this.current].name);
 },
 playlistChange: function(index) {
 this.playlistConfig(index);
 $(this.cssSelector.jPlayer).jPlayer("play");
 },
 playlistNext: function() {
 var index = (this.current + 1 <this.playlist.length)? this.current + 1 : 0;
 this.playlistChange(index);
 },
 playlistPrev: function() {
 var index = (this.current - 1> = 0)? this.current - 1 : this.playlist.length - 1;
 this.playlistChange(index);
 }
}; 
}//The createplaylist() function is called from the searchaudio()
//function which in turn is called when the playlist is changed or audio search is done.
//So when new audiolist is formed, new playlist is initialized for it
//and new instance of Jplayer is created for it.function createplaylist()
{
 var objectarraystring="var myaudioplaylist=[";
 $(".audiotrack").each(function(){
 objectarraystring=objectarraystring+"{name:""+$(this).text()+
"",mp3:""+$(this).attr('url')+""},";
 });
 objectarraystring+="]";
 eval(objectarraystring);
 audioPlaylist = new window.Playlist("2",myaudioplaylist, {
 ready: function() {
 audioPlaylist.playlistInit(false);//Parameter is a boolean for autoplay.
 },
 ended: function() {
 audioPlaylist.playlistNext();
 },
 play: function() {
 $(this).jPlayer("pauseOthers");
 },
 swfPath:"flash",
 supplied:"mp3",
 solution:"html, flash",
 wmode:"window",
 preload:"auto"
});
}

[script_audio.js]

> 旋转盘

旋转盘是透明png图像 [ rotating_disc.png ]。 这里图像在coverart图像 [ coverart.png ] 上放置适当的( 通过对纵横比 等等 进行一些计算)。 当我们使用鼠标右键转换音频时,我们会根据浏览器的属性,使用适当的名称来旋转( 角度),因为不同的浏览器会使用不同的名称。

让我们看一下在网络画廊中看到的旋转光盘的屏幕截图:

333670/rotating_disc.jpg

现在让我们看一下不同文件的代码,使之发生:

<divid="coverart"><imgsrc="image/audiogallery_images/coverart.png"oriwidth="693"oriheight="680"width="693"height="680"alt="coverart"/><imgid="rotatingdisc"src="image/audiogallery_images/rotating_disc.png"width="350"height="350"alt="rotatingdisc"/></div>

[index.html]

$(document).ready(function(){
 //Other code is present here, see source files. Removed for clarity//adding audioplaying status data to my player and starting the disc $("#jquery_jplayer_2").bind($.jPlayer.event.play, function() { 
 $("#player").data("audioplaying",true);
 startdisk(); });
 //adding audioplaying status data to my player and stopping the disc $("#jquery_jplayer_2").bind($.jPlayer.event.pause, function() {
 $("#player").data("audioplaying",false);
 stopdisk(); }); 
});function setdimensions()
{//Other code is present here, see source files. Removed for clarity// Making the coverart rotatingdisc to the correct size and positioning it$("#rotatingdisc").width($("#coverart img").width()/1.98);
$("#rotatingdisc").height($("#rotatingdisc").width());varrotatingdiscleftposition=
 $("#coverart img").position().left+$("#coverart img").width()/2.240896;varrotatingdisctopposition=
 $("#coverart img").position().top+$("#coverart img").height()/4.65753;$("#rotatingdisc").css('left',rotatingdiscleftposition);
$("#rotatingdisc").css('top',rotatingdisctopposition);//rotatingdisc code end}//Rotate disk at regular intervals by specified anglefunctionrotatedisk(element,angle) 
{
 stopdisk();
 element.stop().animate({rotate: '+=150deg'}, 800, 'easeInCubic', function() {
 var intervalid = setInterval(
 function () {
 element.animate({rotate: '+=' + angle + 'deg'}, 0);
 },
 25 );
 element.data('intervalid', intervalid);
 });
}functionstopdisk()
{
 var intervalid = $('#rotatingdisc').data('intervalid');
 clearInterval(intervalid);
 $('#rotatingdisc').stop().animate({rotate: '+=150deg'}, 800, 'easeOutCubic'); 
}functionstartdisk()
{
 var randnum=Math.floor(Math.random() * (60 - 10 + 1) + 10);
 //remove this if it doesn't suite you rotatedisk($('#rotatingdisc'),randnum);
}

[script_audio.js]

> 键盘支持

网络画廊的音频播放器也可以通过键盘键控制。 这使得网络画廊的用户易于访问并控制玩家。 在事件事件中,根据键执行了一个操作,并执行了一个操作。 在名为 [ initplayerkeyboardsupport ]的函数中,keydown事件及其事件处理程序的绑定是 encapsulauted,在DOM准备好 例如 ( 在 $(document).ready(function(){---}); 中) 时调用。

让我们看看显示可以用于控制播放器的按键的屏幕截图:

333670/keyboard_support.jpg

现在让我们看看使它发生的代码:

functioninitplayerkeyboardsupport()
{
 $(document).keydown(function(event)
 {
 //for seekingif (event.shiftKey)
 {
 switch (event.keyCode) 
 {
 case37: // SHIFT + left arrow $("#player").data("currenttime")-1>=0?$("#jquery_jplayer_2").jPlayer(
 "playHead", $("#player").data("currenttime")-1):null;
 if (($("#player").data("currenttime")-1)>=0)
 {
 if ($("#player").data("audioplaying"))
 {
 $("#jquery_jplayer_2").jPlayer("play", 
 $("#player").data("currenttime")-1);
 $("#jquery_jplayer_2").jPlayer("play");
 }
 else {
 $("#jquery_jplayer_2").jPlayer("pause", 
 $("#player").data("currenttime")-1); 
 }
 }
 return;
 break;
 case39: // SHIFT + right arrowif (($("#player").data("currenttime")+1)<=$(
 "#player").data("currenttrackduration"))
 {
 if($("#player").data("audioplaying"))
 {
 $("#jquery_jplayer_2").jPlayer("play", 
 $("#player").data("currenttime")+1);
 $("#jquery_jplayer_2").jPlayer("play");
 }
 else {
 $("#jquery_jplayer_2").jPlayer("pause", 
 $("#player").data("currenttime")+1);
 }
 }
 return;
 break;
 } 
 }
 switch (event.keyCode) 
 {
 case37: // left arrow window.audioPlaylist!=undefined?window.audioPlaylist.playlistPrev():null;
 break;
 case39: // right arrow window.audioPlaylist!=undefined?window.audioPlaylist.playlistNext():null;
 break;
 case32: // spaceif ($("#player").data("audioplaying")===false || 
 $("#player").data("audioplaying")===undefined)
 {
 $("#jquery_jplayer_2").jPlayer("play");
 $("#player").data("audioplaying",true);
 }
 else {
 $("#jquery_jplayer_2").jPlayer("pause");
 $("#player").data("audioplaying",false); 
 }
 break;
 case77: // mif ($("#player").data("muted")===false || 
 $("#player").data("muted")===undefined)
 {
 $("#jquery_jplayer_2").jPlayer("mute");
 $("#player").data("muted",true);
 }
 else {
 $("#jquery_jplayer_2").jPlayer("unmute");
 $("#player").data("muted",false); 
 }
 break;
 case109: // Mif ($("#player").data("muted")===false || 
 $("#player").data("muted")===undefined)
 {
 $("#jquery_jplayer_2").jPlayer("mute");
 $("#player").data("muted",true);
 }
 else {
 $("#jquery_jplayer_2").jPlayer("unmute");
 $("#player").data("muted",false); 
 }
 break;
 }
 });
}

[script_audio.js]

> 下载音频

音频改变后,它更改 jplayer"setMedia"方法changed在Playlist类div方法中使用数据,将当前音轨url信息添加到播放机div子菜单中,以为单位显示当前音轨url信息。j。 这样做的时候,我总是有的变量指向当前播放的音轨,因为当音频改变时,变量 [currenttrackurl] 被分配一个新/当前值。 所以现在在下载按钮click点击事件处理程序i [currenttrackurl] 变量value然后发送到 [downloadengine.php],然后开始下载这个特定文件的下载。

让我们看到一个下载按钮的屏幕截图,如网页剪辑所示:

333670/download.jpg

现在让我们看看来自不同文件的代码,让它发生:

<aid="downloadaudiotool"target="_blank"class="button gray medium">DOWNLOAD</a>

[index.html]

$(document).ready(function(){//Other code is present here, see source files. Removed for clarity$("#downloadaudiotool").click(function(){
 var filedownloadpath=encodeURIComponent($("#player").data("currenttrackurl")); $("#downloadaudiotool").attr('href','php/downloadengine.php?file='+filedownloadpath);
});
});function initjplayerplaylistfunctions()
{
 Playlist = function(instance, playlist, options) {
 //Other code is present here, see source files. Removed for clarityplaylistConfig: function(index) {
 $(this.cssSelector.playlist + "_item_" + this.current).removeClass(
 "jp-playlist-current").parent().removeClass("jp-playlist-current");
 $(this.cssSelector.playlist + "_item_" + index).addClass(
 "jp-playlist-current").parent().addClass("jp-playlist-current");
 this.current = index;
 $(this.cssSelector.jPlayer).jPlayer("setMedia", 
 this.playlist[this.current]);
 $("#nowplaying span").text(this.playlist[this.current].name);
 $("#player").data("currenttrackurl",this.playlist[this.current].mp3); playlistuiupdate(1,$('#player').data("currenttrackindex"),index);
 $('#player').data("currenttrackindex",index);
 shareupdate($("#player").data("currenttrackurl"),this.playlist[this.current].name);
}

[script_audio.js]

> 音频共享

音频共享使用AddThis实用工具 (http://www.addthis.com/)。 每个新音频都设置好后,我在从DOM中删除旧实例后创建了新实例,因为AddThis很容易实现,因为很容易实现,因此我使用了这个简单的解决方案,使它更容易实现。

让我们看一下 web gallery中看到的共享按钮的屏幕截图:

333670/share.jpg

现在让我们看看使它发生的代码:

function initjplayerplaylistfunctions()
{
 Playlist = function(instance, playlist, options) 
 {
//Other code is present here, see source files. Removed for clarity
 playlistConfig: function(index) 
 {
 $(this.cssSelector.playlist +"_item_" + this.current).removeClass(
"jp-playlist-current").parent().removeClass("jp-playlist-current");
 $(this.cssSelector.playlist +"_item_" + index).addClass(
"jp-playlist-current").parent().addClass("jp-playlist-current");
 this.current = index;
 $(this.cssSelector.jPlayer).jPlayer(
"setMedia", this.playlist[this.current]);
 $("#nowplaying span").text(this.playlist[this.current].name);
 $("#player").data("currenttrackurl",this.playlist[this.current].mp3);
 playlistuiupdate(1,$('#player').data("currenttrackindex"),index);
 $('#player').data("currenttrackindex",index);
 shareupdate($("#player").data(
"currenttrackurl"),this.playlist[this.current].name);
 }
 }
}
function shareupdate(url,title)
{
 $('#addthissharetool').remove(); $('#toolbar').append('<a id="addthissharetool" ' + 
 'class="sharebar-trigger button gray medium">SHARE</a>');
 url=encodeURI(url);
 addthis.button( '#addthissharetool',
 {
 ui_click: true,
 ui_open_windows:true,
 },
 {
 url:url,
 title:title,
 description:'Visit robinrizvi.info'
 }
 );
//Create gray to blue hover effect for toolbar buttons
 $("#addthissharetool").hover(function(){
 $(this).removeClass('button gray medium').addClass('button blue medium');
 },
 function(){
 $(this).removeClass('button blue medium').addClass('button gray medium');
 }
 );
}

[script_audio.js]

4库软件

让我们看看库管理软件的基本功能和固有功能和特性在代码中如何实现。 gallery管理软件中的大部分代码都是以支持多线程架构为用户提供快速响应和非阻塞UI体验。 这些代码稍微有点 flavor 3-tier,并且几乎所有数据库交互所需的代码都存在于的static 类中,称为用户 [user.cs]。 我不会讨论 [user] 类,因为它包含名称自己解释的函数,并且可以检查源文件并阅读代码。

让我们看一个截图,给出画廊软件的概述:

333670/gallery_software.jpg

现在让我们从讨论库软件的基本功能和它们的实现开始。

登录

用户输入凭证后,这些凭证的将被传递给用户类 [user.cs]的。 如果你使用的是用户名和密码,则 user.login() 方法将为数据库中的[user] table 搜索一个记录,并将该用户类的名称/变量( static ) 设置为 true,否则为 false。 通过检查 user.isvalid 值,确定输入的用户名和密码是否正确,并相应地采取适当的操作。

让我们看一下登录表单的屏幕截图:

333670/sw1.jpg

现在让我们看看使它发生的代码:

privatevoid loginbtn_Click(object sender, EventArgs e)
{
 if (unametxt.Text!= string.Empty && pwdtxt.Text!= string.Empty)
 {
 userstatuspic.Visible = false;
 loginloadingindicator.Visible = true;
 loginloadingindicator.Active = true;
 unametxt.Enabled = false;
 pwdtxt.Enabled = false;
 loginbtn.Enabled = false;
 Thread loginthread = new Thread(user.login); string[] unamepwd = { unametxt.Text, pwdtxt.Text };
 loginthread.Start(unamepwd);while (loginthread.IsAlive) Application.DoEvents();
  if (user.isvalid) {
 userstatuspic.Image = Properties.Resources.user_accept;
 userstatuspic.Visible = true;
 loginloadingindicator.Visible = false;
 loginloadingindicator.Active = false;
 Application.DoEvents();
 Thread.Sleep(2000);
 main mainfrm = new main();
 this.Hide();
 mainfrm.ShowDialog();
 this.Close();
 }
 else {
 userstatuspic.Image = Properties.Resources.user_remove;
 unametxt.Enabled = true;
 pwdtxt.Enabled = true;
 loginbtn.Enabled = true;
 userstatuspic.Visible = true;
 loginloadingindicator.Visible = false;
 loginloadingindicator.Active = false;
 }
 }
 else MessageBox.Show("Please fill in all the fields.");
}

[login.cs]

显示播放列表

主表单加载后,调用函数,然后调用用户类 [user.cs]的方法。 user.getplaylists() 方法查询数据库中的播放列表 table 以获取由用户( 目前使用画廊软件) 创建的播放列表。 user.getplaylists() 方法将数据库查询返回的播放列表到 user.playlists 集合( 见下面的代码)。

publicstruct playlist{
 publicUInt64 id;
 publicstring name;
 publicstring description;
 publicstring thumb;
}publicstaticList<playlist> playlists = new List<playlist>();publicstaticvoidgetplaylists()//reads the records from playlist table and for each entry calls//downloadplaylist() to download the thumb and save it into local temp foler{
 playlists.Clear();
 try {
 if (conn.State == ConnectionState.Closed) conn.Open();
 string query = "SELECT * FROM playlist WHERE user_id=@userid";
 MySqlCommand cmd = new MySqlCommand(query, conn);
 cmd.Parameters.AddWithValue("@userid", userid);
 MySqlDataReader rdr = cmd.ExecuteReader();
 while (rdr.Read())
 {
 playlist a1;
 a1.id = UInt64.Parse(rdr["id"].ToString());
 a1.name = rdr["name"].ToString();
 a1.description = rdr["description"].ToString();
 a1.thumb = rdr["thumb"].ToString();
 if (downloadplaylistthumb(a1)) playlists.Add(a1);
 }
 conn.Close();
 }
 catch (Exception)
 {
 System.Windows.Forms.MessageBox.Show("The connection to the database could" + 
 "not be made. Please check your internet connection." + 
 Environment.NewLine+"The application will now exit.");
 System.Windows.Forms.Application.Exit();
 }
}

[user.cs]

播放播放列表,然后在主表单中添加每个播放列表,并向列表中添加

privatevoid showplaylists()
{
 Thread getplaylistthread = new Thread(user.getplaylists); getplaylistthread.Start();
 while (getplaylistthread.IsAlive) Application.DoEvents();
 playlistimagelist.Images.Clear();
 playlistview.Items.Clear();
 foreach (user.playlist playlist in user.playlists)
 {
 string filename = Application.StartupPath + 
 "tempplaylist_" + playlist.id + "" + playlist.thumb;
 Bitmap img = new Bitmap(filename);
 playlistimagelist.Images.Add(playlist.id.ToString(), img);
 playlistview.Items.Add(playlist.name, playlist.id.ToString()); }
}

[main.cs]

让我们看看在主表单中显示 playlistView ( Listview )的屏幕截图:

333670/playlistview.jpg

显示音频

选择播放列表时,( 点击它) 将调用 showaudios() 函数,然后调用用户类 [user.cs]的getaudios() 方法。 user.getaudios() 函数要求 playlist_id 作为参数,它根据这里参数( playlist_id ) 查询属于特定播放列表( 他的playlist_id )的音频 table。 方法存储由数据库查询向 user.audios 集合 ( 查看代码 below ) 返回的音频

publicstruct audio{
 publicUInt64 id;
 publicstring name;
 publicstring title;
 publicstring description;
}publicstaticList<audio> audios = new List<audio>();publicstaticvoidgetaudios(object data)//reads records from the audio table for a particular albumid and then saves the entries in the pictures list{
 Int32 currentplaylistid = (Int32)data;
 audios.Clear();
 try {
 if (conn.State == ConnectionState.Closed) conn.Open();
 string query = "SELECT * FROM audio WHERE playlist_id=@playlistid";
 MySqlCommand cmd = new MySqlCommand(query, conn);
 cmd.Parameters.AddWithValue("@playlistid", currentplaylistid);
 MySqlDataReader rdr = cmd.ExecuteReader();
 while (rdr.Read())
 {
 audio p1;
 p1.id = UInt64.Parse(rdr["id"].ToString());
 p1.name = rdr["name"].ToString();
 p1.title = rdr["title"].ToString();
 p1.description = rdr["description"].ToString();
 if (downloadaudio(p1, currentplaylistid)) audios.Add(p1);
 //add the audios to the list }
 conn.Close();
 }
 catch (Exception)
 {
 System.Windows.Forms.MessageBox.Show("The connection to the database could not be made." + 
 "Please check your internet connection." + 
 Environment.NewLine+"The application will now exit.");
 System.Windows.Forms.Application.Exit();
 }
}

[user.cs]

音频存储在 user.audios collection(List), 之后,控件返回到 showaudios() 函数,并且在 user.audios 集合中的每个音频在主窗体中添加到 Listview。

private void showaudios(Int32 currentplaylistid){
 Thread getaudiothread = new Thread(user.getaudios);
 getaudiothread.Start(currentplaylistid);while (getaudiothread.IsAlive) Application.DoEvents();
 audioimagelist.Images.Clear();
 audiolistview.Items.Clear();
 foreach (user.audio audio in user.audios)
 {
 audioimagelist.Images.Add(audio.id.ToString(), Properties.Resources.audio);
 audiolistview.Items.Add(audio.title, audio.id.ToString()); }
}

[main.cs]

让我们看看在主表单中显示 audiolistview ( Listview )的屏幕截图:

333670/audiolistview.jpg

添加播放列表

当用户点击 playlist playlist主窗体上的[ADD] 按钮时,的addplaylist [addplaylist.cs] 表单将打开

让我们看一下addplaylist格式的sreenshot:

333670/sw5.jpg

收费收费表要求用户填写要创建的播放列表和描述,用户还必须提供一个缩略图来代表播放列表。 填写这些信息后,用户必须单击 [ADD PLAYLIST] 按钮,然后执行 playlistadd() 执行该播放列表实际任务的函数。 创建播放列表收费涉及三个基本步骤:

  • 在数据库中为新播放列表添加 [playlist] 表中的记录
  • 在远程服务器( 请参见目录结构部分 上面 ) 上为播放列表创建文件夹
  • 向远程服务器上传播放列表的缩略图

让我们看一下如何实现这些 3个基本步骤的代码:

privatevoidplaylistadd()
{
 int thumbnailwidth = 150;
 int thumbnailheight = 150;
 try {
 #region add records in the playlist table for the new playlistUInt32 newaddedplaylistid = user.addplaylist(
 nametxt.Text, new FileInfo(thumbnametxt.Text).Name, descriptiontxt.Text);
 if (newaddedplaylistid == 0) thrownew Exception();
 #endregiontry {
 #region creating folders for the playlist on the remote server//creating playlist folderstringcreatepath = user.ftpurl + "user_" + 
 user.userid + "/playlist_" + newaddedplaylistid;
 FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(createpath);
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 request.KeepAlive = true;
 request.Method = WebRequestMethods.Ftp.MakeDirectory;
 request.GetResponse();//creating audios folder in the playlist foldercreatepath = user.ftpurl + "user_" + user.userid + 
 "/playlist_" + newaddedplaylistid + "/audios";
 request = (FtpWebRequest)FtpWebRequest.Create(createpath);
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 request.KeepAlive = true;
 request.Method = WebRequestMethods.Ftp.MakeDirectory;
 request.GetResponse();#endregion#region uploading thumbnail of the playlist to the remote servertry {
 int ChunkSize = 4096, NumRetries = 0, MaxRetries = 20;
 byte[] Buffer = new byte[ChunkSize];
 string onlythumbname = new FileInfo(thumbnametxt.Text).Name;
 Image thumbimg = Image.FromFile(thumbnametxt.Text).GetThumbnailImage(
 thumbnailwidth, thumbnailheight, thumbnailcreationfailedcallback, IntPtr.Zero);
 MemoryStream thumbimgstream = new MemoryStream();
 thumbimg.Save(thumbimgstream, System.Drawing.Imaging.ImageFormat.Jpeg);
 thumbimgstream.Position = 0;
 stringUploadPath = user.ftpurl + "user_" + 
 user.userid + "/playlist_" + newaddedplaylistid + "/" + onlythumbname;
 request = (FtpWebRequest)WebRequest.Create(UploadPath);
 request.Method = WebRequestMethods.Ftp.UploadFile;
 request.KeepAlive = true;
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 using (Stream requestStream = request.GetRequestStream())
 {
 using (thumbimgstream)
 {
 int BytesRead = thumbimgstream.Read(Buffer, 0, ChunkSize);
 // read the first chunk in the buffer// send the chunks to the web service one by one, until// FileStream.Read() returns 0, meaning the entire file has been read.while (BytesRead >0)
 {
 try {
 requestStream.Write(Buffer, 0, BytesRead); }
 catch {
 if (NumRetries++ < MaxRetries)
 {
 // rewind the imagememeorystream and keep trying thumbimgstream.Position -= BytesRead;
 }
 else {
 thrownew Exception();
 }
 }
 BytesRead = thumbimgstream.Read(Buffer, 0, ChunkSize);
 // read the next chunk (if it exists) into the buffer.// the while loop will terminate if there is nothing left to read }
 }
 }
 }
 catch (Exception)
 {
 //thumbnail could not be uploaded so remote folders have to be deleted#region deleting folder that were created for the playliststring deletepath = user.ftpurl + "user_" + user.userid + 
 "/playlist_" + newaddedplaylistid;
 new DeleteFTPDirectory().DeleteDirectoryHierarcy(deletepath);
 #endregionthrownew Exception();
 }
 #endregion }
 catch (Exception)
 {
 #region deleting playlist record from the database//If folder could not be created or thumbnail could not be created//remove the playlist record from the playlist table in the database user.deleteplaylist(newaddedplaylistid);
 thrownew Exception();
 #endregion }
 }
 catch (Exception)
 {
 MessageBox.Show("The playlist could not be added");
 return;
 }
 MessageBox.Show("The playlist has been added");
 //this.Close();}

[addplaylist.cs]

编辑播放列表

当用户点击 playlist playlist主窗体上的[EDIT] 按钮时,的editplaylist [editplaylist.cs] 表单将打开

让我们看一下editplaylist格式的屏幕截图:

333670/sw8.jpg

[editplaylist] 表显示了可以由用户编辑的播放列表信息。 用户在编辑信息后,必须按按钮然后执行执行该播放列表的实际任务的playlistedit() 函数。 编辑播放列表收费包括两个基本步骤:

  • 数据库数据库中 [playlist] table 中的更新记录。
  • 将播放列表的缩略图 到远程服务器,如果缩略图已经更改。

让我们看一下如何实现这些基本步骤的代码:

privatevoidplaylistedit()
{
 bool thumbuploaded = true;
 if (new FileInfo(thumbnametxt.Text).Name!= playlisttoedit.thumb) {
 #region uploading thumbnail of the playlist to the remote servertry {
 int thumbnailwidth = 150;
 int thumbnailheight = 150;
 int ChunkSize = 4096, NumRetries = 0, MaxRetries = 20;
 byte[] Buffer = new byte[ChunkSize];
 string onlythumbname = new FileInfo(thumbnametxt.Text).Name;
 Image thumbimg = Image.FromFile(thumbnametxt.Text).GetThumbnailImage(thumbnailwidth, 
 thumbnailheight, thumbnailcreationfailedcallback, IntPtr.Zero);
 MemoryStream thumbimgstream = new MemoryStream();
 thumbimg.Save(thumbimgstream, System.Drawing.Imaging.ImageFormat.Jpeg);
 thumbimgstream.Position = 0;
 string UploadPath = user.ftpurl + "user_" + user.userid + 
 "/playlist_" + playlisttoedit.id + "/" + onlythumbname;
 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(UploadPath);
 request.Method = WebRequestMethods.Ftp.UploadFile;
 request.KeepAlive = true;
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 using (Stream requestStream = request.GetRequestStream())
 {
 using (thumbimgstream)
 {
 // read the first chunk in the bufferint BytesRead = thumbimgstream.Read(Buffer, 0, ChunkSize);
 // send the chunks to the web service one by one, until FileStream.Read()// returns 0, meaning the entire file has been read.while (BytesRead >0)
 {
 try {
 requestStream.Write(Buffer, 0, BytesRead);
 }
 catch {
 if (NumRetries++ < MaxRetries)
 {
 // rewind the imagememeorystream and keep trying thumbimgstream.Position -= BytesRead;
 }
 else {
 thrownew Exception();
 }
 }
 BytesRead = thumbimgstream.Read(Buffer, 0, ChunkSize);
 // read the next chunk (if it exists) into the buffer.// the while loop will terminate if there is nothing left to read }
 }
 }
 }
 catch (Exception)
 {
 //thumbnail could not be uploaded thumbuploaded = false;
 }
 #endregion }
 if (thumbuploaded)
 {
 if (!(user.updateplaylist((UInt32)playlisttoedit.id, nametxt.Text, 
 new FileInfo(thumbnametxt.Text).Name, descriptiontxt.Text)))
 {
 #region deleting the new thumbnail that was uploaded  because the entry in the database could not be made
 if (new FileInfo(thumbnametxt.Text).Name!= playlisttoedit.thumb)
 {
 try {
 string deletepath = user.ftpurl + "user_" + user.userid + "/playlist_" + 
 playlisttoedit.id + "/" + new FileInfo(thumbnametxt.Text).Name;
 FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(deletepath);
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 request.Method = WebRequestMethods.Ftp.DeleteFile;
 request.KeepAlive = true;
 request.GetResponse();
 }
 catch (Exception)
 {
 //do nothing if thumb could not be deleted,//later on it'll be done via garbage collector  }
 }
 #endregion MessageBox.Show("The playlist could not be updated");
 }
 else {
 #region deleting the old playlist thumb from the remote server and the local temp folderif (new FileInfo(thumbnametxt.Text).Name!= playlisttoedit.thumb)
 {
 try {
 string deletepath = user.ftpurl + "user_" + user.userid + 
 "/playlist_" + playlisttoedit.id + "/" + playlisttoedit.thumb;
 FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(deletepath);
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 request.Method = WebRequestMethods.Ftp.DeleteFile;
 request.KeepAlive = true;
 request.GetResponse();
 //deleting the old thumb from the local temp folder deletepath = Application.StartupPath + "tempplaylist_" + 
 playlisttoedit.id + "" + playlisttoedit.thumb;
 if (File.Exists(deletepath)) File.Delete(deletepath);
 }
 catch (Exception)
 {
 //do nothing if old thumb could not be deleted,//later on it'll be done via garbage collector  }
 }
 #endregion MessageBox.Show("The playlist has been updated");
 }
 }
 else {
 MessageBox.Show("The playlist could not be updated");
 }
}

[editplaylist.cs]

Delete 播放列表

当用户单击播放列表窗格中主窗体的[DELETE] 按钮时,将选择当前活动的播放列表进行删除。 删除播放列表涉及两个基本步骤:

  • 在 [playlist] 表中按删除记录,并在数据库中为所选播放列表创建 [audio] 表。
  • 在远程服务器上为该播放列表创建的Delete 文件夹

让我们看一下如何实现这些步骤的代码:

privatevoiddeleteplaylistbtn_Click(object sender, EventArgs e)
{
 if (playlistview.SelectedItems.Count >0)
 {
 if (DialogResult.OK == MessageBox.Show("Are you sure you want to delete the playlist?", 
 "Delete Playlist", MessageBoxButtons.OKCancel))
 {
 UInt32 playlisttodeleteid = UInt32.Parse(playlistview.SelectedItems[0].ImageKey);
 try {
 if (!(user.deleteplaylist(playlisttodeleteid))) thrownew Exception();
 Thread deleteplaylistthread = new Thread(deleteplaylistthreadfunction);
 deleteplaylistthread.Start(playlisttodeleteid);
 }
 catch (Exception)
 {
 MessageBox.Show("Sorry the playlist could not be deleted");
 return;
 }
 //MessageBox.Show("Playlist has been deleted.");#region refresh the main form playlistloadingindicator.Visible = true;
 playlistloadingindicator.Active = true;
 showplaylists();
 playlistloadingindicator.Active = false;
 playlistloadingindicator.Visible = false;
 audioloadingindicator.Visible = true;
 audioloadingindicator.Active = true;
 if (playlistview.Items.Count >0)
 {
 user.currentplaylistid = Int32.Parse(playlistview.Items[0].ImageKey);
 showaudios(user.currentplaylistid);
 }
 else audiolistview.Items.Clear();
 audioloadingindicator.Active = false;
 audioloadingindicator.Visible = false;
 #endregion }
 }
 else MessageBox.Show("Please select the playlist to delete");
}privatevoiddeleteplaylistthreadfunction(object data)
{
 UInt32 playlisttodeleteid = (UInt32)data;
 deleteplaylist frm = new deleteplaylist(playlisttodeleteid);
 frm.ShowDialog();
}

[main.cs]

voidfolderdeletionthread()
{
 #region deleting folder that were created for the playlist  on the remote serverand the local temp foldertry {
 //deleting on the remote serverstringdeletepath = user.ftpurl + "user_" + 
 user.userid + "/playlist_" + playlisttodeleteid;
 newDeleteFTPDirectory().DeleteDirectoryHierarcy(deletepath);
 //deleting on the local temp folder deletepath = Application.StartupPath + "tempplaylist_" + playlisttodeleteid;
 if (Directory.Exists(deletepath)) Directory.Delete(deletepath, true);
 }
 catch (Exception)
 {
 //In case the remote folders could not be deleted//I'll do nothing they will later be garbage collected }
 #endregion}

[deleteplaylist.cs]

> 添加音频

当用户点击 audios pane主表单的[ADD] 按钮时,的上传 [upload.cs] 表单将打开

让我们看一下上传表单的屏幕截图:

333670/sw7.jpg

收费的表单要求用户填写要上载的音频的标题和描述。 填写这些信息后,用户必须点击 [UPLOAD AUDIO] 按钮,然后执行 fileuploadbackgroundworker_DoWork() 函数( background 工作线程异步执行) 执行/上传音频的实际任务。 上传音频包括以下基本步骤:

  • 在数据库的[audio] table 中为上传的音频添加记录。
  • 向远程服务器( 请参见目录结构部分 上面 )的音频目录中上传音频。 使用. NET's FTPWEBREQUEST 类( ) 上传音频。
  • 当上传音频时,报告进度,显示上传的音频的百分比和字节。

让我们看一下如何实现这些基本步骤的代码:

privatevoiduploadfilesbtn_Click(object sender, EventArgs e)
{
 if (filename!= string.Empty && titletxt.Text!= 
 string.Empty && descriptiontxt.Text!= string.Empty)
 {
 uploadfilebtn.Enabled = false;
 uploadfilebtn.Text = "PLEASE WAIT";
 addcoverart(filename, "poster.jpg");
 fileuploadbackgroundworker.RunWorkerAsync(filename); }
 else MessageBox.Show("Please fill in all the fields");
}privatevoidfileuploadbackgroundworker_DoWork(object sender, DoWorkEventArgs e)
{
 string UploadPath;
 FtpWebRequest request;
 int ChunkSize = 102400, NumRetries = 0, MaxRetries = 3;
 byte[] Buffer = new byte[ChunkSize];
 //for updating status to the ui threaddecimal totalbytes = new FileInfo(filename).Length;
 decimal totalbytesuploaded = 0;
 //end#region upload to remote, make database records,report progress to ui threadstring onlyfilename = new FileInfo(filename).Name;
 bool fileuploadedremotely = true;
 try {
 if (fileuploadedremotely)
 {
 #region upload audio to remote serverUploadPath = user.ftpurl + "user_" + user.userid + 
 "/playlist_" + user.currentplaylistid + "/audios/" + onlyfilename;
 request = (FtpWebRequest)WebRequest.Create(UploadPath);
 request.Method = WebRequestMethods.Ftp.UploadFile;
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 using (Stream requestStream = request.GetRequestStream())
 {
 using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read))
 {
 int BytesRead = fs.Read(Buffer, 0, ChunkSize);
 // read the first chunk in the buffer// send the chunks to the web service one by one,// until FileStream.Read() returns 0, meaning the entire file has been read.while (BytesRead >0)
 {
 try {
 requestStream.Write(Buffer, 0, BytesRead); totalbytesuploaded += BytesRead;
 #region report progress to the ui threadint percentage = (int)(((float)totalbytesuploaded * 100)/((float)totalbytes));
 string statustext = string.Format("{0:0.00} Mb/{1:0.00} Mb", 
 (float)(totalbytesuploaded/(1024 * 1024)), (float)(totalbytes/(1024 * 1024)));
 fileuploadbackgroundworker.ReportProgress(percentage, statustext);#endregion }
 catch {
 if (NumRetries++ < MaxRetries)
 {
 // rewind the filestream and keep trying fs.Position -= BytesRead;
 }
 else {
 //MessageBox.Show("Could not upload" + onlyfilename + //" after several attempts./// Please check your network connectivity. This file will be skipped."); fileuploadedremotely = false;
 break;
 }
 }
 BytesRead = fs.Read(Buffer, 0, ChunkSize);
 // read the next chunk (if it exists) into the buffer.// the while loop will terminate if there is nothing left to read }
 }
 }
 #endregion }
 if (fileuploadedremotely)
 {
 #region add record to the databaseif (!user.insertaudio(onlyfilename, titletxt.Text, 
 descriptiontxt.Text, user.currentplaylistid)) fileuploadedremotely = false;
 #endregion }
 }
 catch {
 fileuploadedremotely = false;
 }
 if (!fileuploadedremotely)
 {
 user.deleteaudio(onlyfilename, user.currentplaylistid);
 MessageBox.Show("The file could not be uploaded." + 
 "The reason could be slow or no internet connectivity");
 filename = string.Empty;
 //code should be written here to delete the audio that was uploaded//but some database error occured but that is a rare chance, so ignoring the code piece here }
 else {
 #region report progress to the ui threadint percentage = 100;
 string statustext = string.Format("{0:0.00} Mb/{1:0.00} Mb", 
 (float)(totalbytes/(1024 * 1024)), (float)(totalbytes/(1024 * 1024)));
 fileuploadbackgroundworker.ReportProgress(percentage, statustext);
 #endregion MessageBox.Show("The file has been uploaded");
 filename = string.Empty;
 }#endregion}privatevoidfileuploadbackgroundworker_ProgressChanged(object sender, 
 ProgressChangedEventArgs e)
{
 progressbar.Value = e.ProgressPercentage;try {
 numofbytesuploadedstatuslbl.Text = e.UserState.ToString(); }
 catch (Exception)
 { 
 //do nothing  }
}privatevoidfileuploadbackgroundworker_RunWorkerCompleted(object sender, 
 RunWorkerCompletedEventArgs e)
{
 uploadfilebtn.Enabled = true;
 uploadfilebtn.Text = "UPLOAD AUDIO";
 progressbar.Value = 0;
 numofbytesuploadedstatuslbl.Text = "Operation Completed";
 filenametxt.Text = "";
 titletxt.Text = "";
 descriptiontxt.Text = "";
 filename = string.Empty;
}

[upload.cs]

编辑音频

当用户点击 audios pane主表单的[EDIT] 按钮时,的更新音频将打开。

让我们看一下更新音频表单的sreenshot:

333670/sw9.jpg

Update Update [editaudio.cs] 表显示用户可以编辑的音频信息。 用户在编辑信息后,必须按按钮然后执行执行实际任务信息更新的audioedit() 函数。 编辑音频收费涉及一个基本的步骤:

  • 更新的音频 [audio] table 中的更新记录。

让我们看一下如何实现它的代码:

privatevoideditaudiobtn_Click(object sender, EventArgs e)
{
 editaudiobtn.Enabled = false;
 titletxt.Enabled = false;
 descriptiontxt.Enabled = false;
 editaudiobtn.Text = "Please Wait...";
 Application.DoEvents();
 if (string.IsNullOrEmpty(nametxt.Text) || string.IsNullOrEmpty(titletxt.Text) || 
 string.IsNullOrEmpty(descriptiontxt.Text))
 {
 MessageBox.Show("Please fill in all the fields");
 }
 else {
 string[] fields = {titletxt.Text,descriptiontxt.Text};
 editaudiothread = new Thread(audioedit);editaudiothread.Start(fields);while (editaudiothread.IsAlive) Application.DoEvents();
 }
 this.Close();
}privatevoidaudioedit(object fields)
{
 string[] title_decription = (string[])fields;
 if (user.updateaudio(audio.id, title_decription[0], title_decription[1]))
 MessageBox.Show("The audio has been updated");
 else MessageBox.Show("The audio could not updated due to a title mismatch" + 
 "or some internal errors. Try changing the title or try again later");
}

[editaudio.cs]

Delete 音频

当用户单击 AUDIOS pane主窗体上的[DELETE] 按钮时,的DELETE 音频 [delete.cs] 窗体将打开

让我们看一下 DELETE 音频格式的sreenshot

DELETE 音频 [delete.cs] 窗体显示了用户选择删除( 可以同时删除多个音频)的音频。 当用户点击 [DELETE AUDIOS] 按钮时,deleteaudiosbackgroundworker_DoWork() 函数( 这是一个异步函数) 被执行,它完成了删除音频的实际任务。 删除音频涉及以下基本步骤:

  • 数据库中 [audio] table的音频的 Delete 记录。
  • 从远程服务器( 请参见目录结构部分 上面 )的音频目录中收取 Delete 音频
  • 报告已经删除的音频的百分比,报告了已经删除音频的百分比和数量。

让我们看一下如何实现这些基本步骤的代码:

privatevoiddeleteaudiobtn_Click(object sender, EventArgs e)
{
 Dictionary<string, string> audios = new Dictionary<string, string>();
 string[] filenames = new string[audiolistview.SelectedItems.Count];
 for (int i=0;i<audiolistview.SelectedItems.Count;i++)
 {
 audios.Add(audiolistview.SelectedItems[i].ImageKey, audiolistview.SelectedItems[i].Text);
 }
 if (audios.Count >0)
 {
 delete frm = new delete(audios);
 frm.ShowDialog(); }
 else MessageBox.Show("Please select some audios to delete");
 //refresh the audio view list box audioloadingindicator.Visible = true;
 audioloadingindicator.Active = true;
 showaudios(user.currentplaylistid);
 audioloadingindicator.Active = false;
 audioloadingindicator.Visible = false;
 //end refresh}

[main.cs]

privatevoiddeleteaudiosbackgroundworker_DoWork(object sender, DoWorkEventArgs e)
{
 long totalfiles = audios.Keys.Count;
 long totalfilesdeleted = 0;
 long totalfilesskipped = 0;
 //selecting each audio one by one and deleting it from database,local temp and remote serverforeach (KeyValuePair<string, string> audio in audios)
 {
 bool filedeleted = false;
 string audiofilename=user.getaudiofilename(ulong.Parse(audio.Key));
 #region deleting audio record from databaseif (user.deleteaudio(ulong.Parse(audio.Key))) filedeleted = true;
 #endregionif (filedeleted == true)
 {
 #region deleting audio from the local temp foldertry {
 string pathtoaudio = Application.StartupPath + "tempplaylist_" + 
 user.currentplaylistid + "audios" + audiofilename;
 if (File.Exists(pathtoaudio)) File.Delete(pathtoaudio);
 }
 catch {
 //do nothing. Later on we can do garbage collection in the local temp folder }
 #endregion }
 if (filedeleted == true)
 {
 #region deleting audio from the remote servertry {
 #region deleting audio from the remote serverstringdeletepath = user.ftpurl + "user_" + user.userid + 
 "/playlist_" + user.currentplaylistid + "/audios/" + audiofilename;
 FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(deletepath);
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 request.KeepAlive = true;
 request.Method = WebRequestMethods.Ftp.DeleteFile;
 request.GetResponse();#endregion }
 catch {
 //do nothing. Later on we could do garbage collection at the remote server }
 #endregion }
 if (filedeleted == true)
 {
 totalfilesdeleted++;
 }
 else {
 totalfilesskipped++;
 }
 long[] userstate=new long[2];
 userstate[0]=totalfilesdeleted;
 userstate[1]=totalfiles;
 int percentage = (int)((float)(totalfilesdeleted * 100)/
 (float)(totalfiles - totalfilesskipped));
 deleteaudiosbackgroundworker.ReportProgress(percentage, userstate); }
 if (totalfilesskipped >0)
 MessageBox.Show("Some of the files could not be deleted");
}privatevoiddeleteaudiosbackgroundworker_ProgressChanged(object sender, 
 ProgressChangedEventArgs e)
{
 string labeltxt = ((long[])e.UserState)[0].ToString() + 
 "/" + ((long[])e.UserState)[1].ToString();
 deletestatuslbl.Text = labeltxt;
 deleteprogressbar.Value = e.ProgressPercentage;}privatevoiddeleteaudiosbackgroundworker_RunWorkerCompleted(object sender, 
 RunWorkerCompletedEventArgs e)
{
 deletestatuslbl.Text = "Operation Completed";
 MessageBox.Show("The delete operation has completed");
 this.Close();
}

[delete.cs]

创建用户

当用户点击按钮时,管理用户的[manageuser.cs] 表单打开。 这里表单包含三个的标签: 创建用户,编辑用户和 Delete 用户。

让我们看一下管理用户表单中的创建用户选项卡的屏幕截图:

填充所有信息后,用户单击 [CREATE USER] 按钮(。查看屏幕截图 上面 ),则执行用户类 [user.cs] 中的createuser() 方法。 创建用户涉及以下基本步骤:

  • 为用户创建数据库中的用户在数据库中添加记录的收费。
  • 为远程服务器上的用户创建目录,格式为 audiogallery/user_id ( 请参见目录结构部分 上面 )。

让我们看一下如何实现这些基本步骤的代码:

publicstaticboolcreateuser(string name,string username,string password,string description)
{
 bool created = true;
 UInt32 userid=0;//Used 0 here creating a new user will never result in a 0 because// I create the superuser with the id=0 myself and don't let it deleted. So...try {
 #region Inserting record in the databaseif (conn.State == ConnectionState.Closed) conn.Open();
 string query = "INSERT INTO user (name,username,password,description)" + 
 " VALUES(@name,@username,@password,@description)";
 MySqlCommand cmd = new MySqlCommand(query, conn);
 cmd.Parameters.AddWithValue("@name", name);
 cmd.Parameters.AddWithValue("@username", username);
 cmd.Parameters.AddWithValue("@password", password);
 cmd.Parameters.AddWithValue("@description", description);
 if (cmd.ExecuteNonQuery() <0) thrownew Exception();
 conn.Close(); 
 #endregion#region Getting the id of newly inserted userif (conn.State == ConnectionState.Closed) conn.Open();
 query = "SELECT id FROM user WHERE username=@username";
 cmd = new MySqlCommand(query, conn);
 cmd.Parameters.AddWithValue("@username", username);
 MySqlDataReader rdr = cmd.ExecuteReader();
 if (rdr.Read()) userid = UInt32.Parse(rdr["id"].ToString());
 elsethrownew Exception();
 conn.Close(); 
 #endregion#region Creating folder for user on the remote sitestringcreatepath = user.ftpurl + "user_" + userid;
 FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(createpath);
 request.Credentials = new NetworkCredential(user.ftpusername, user.ftppassword);
 request.KeepAlive = true;
 request.Method = WebRequestMethods.Ftp.MakeDirectory;
 request.GetResponse(); 
 #endregion }
 catch {
 created = false;
 #region Deleting record from the databaseif (userid!= 0)
 {
 if (conn.State == ConnectionState.Closed) conn.Open();
 string query = "DELETE FROM user WHERE id=@id";
 MySqlCommand cmd = new MySqlCommand(query, conn);
 cmd.Parameters.AddWithValue("@id", userid);
 cmd.ExecuteNonQuery();
 conn.Close();
 }
 #endregion }
 return created;
}
[user.cs] > 编辑用户

当用户点击 [Edit User] tab时,的编辑用户标签就变得可见。

让我们看一下管理用户表单中的编辑用户选项卡的屏幕截图:

当用户在更新所有/部分信息后单击 [EDIT USER] 按钮(。查看屏幕截图 上面 ) 时,将执行用户类 [user.cs] 中的edituser() 方法。 user.edituser() 方法执行更新SQL查询来更新特定用户的所有信息。

让我们看一下如何实现这些基本步骤的代码:

publicstaticbooledituser(UInt32 id,string name, 
 string username, string password, string description)
{
 bool edited = true;
 try {
 if (conn.State == ConnectionState.Closed) conn.Open();
 string query = "UPDATE user SET name=@name,username=@username," + 
 "password=@password,description=@description WHERE id=@id";
 MySqlCommand cmd = new MySqlCommand(query, conn);
 cmd.Parameters.AddWithValue("@id", id);
 cmd.Parameters.AddWithValue("@name", name);
 cmd.Parameters.AddWithValue("@username", username);
 cmd.Parameters.AddWithValue("@password", password);
 cmd.Parameters.AddWithValue("@description", description);
 if (cmd.ExecuteNonQuery() <0) thrownew Exception();
 conn.Close();
 }
 catch {
 edited = false;
 }
 return edited;
}
[user.cs] Delete 用户

当用户单击 [Delete User] 时,的Delete 用户选项卡就会显示出来。

让我们看一下管理用户表单中 Delete 用户选项卡的屏幕截图:

当用户从用户( dropdownlist ) ( 参见截图 上面 ) 选择用户后,将执行用户类 [user.cs]的deleteuser() 方法。 删除用户涉及以下基本步骤:

  • 从数据库中的[user] table 中为用户删除 Delete 记录。
  • 删除远程服务器( 请参见创建用户部分 上面 ) 上为该用户创建的目录的

让我们看一下如何实现这些基本步骤的代码:

publicstaticbooldeleteuser(UInt32 id)
{
 bool deleted = true;
 try {
 #region Deleting record from the databaseif (conn.State == ConnectionState.Closed) conn.Open();
 string query = "DELETE FROM user WHERE id=@id";
 MySqlCommand cmd = new MySqlCommand(query, conn);
 cmd.Parameters.AddWithValue("@id", id);
 if (cmd.ExecuteNonQuery() <0) thrownew Exception();
 conn.Close();
 #endregion#region Delete folder of the user on the remote sitestringdeletepath = user.ftpurl + "user_" + id;newDeleteFTPDirectory().DeleteDirectoryHierarcy(deletepath);#endregion }
 catch {
 deleted = false;
 }
 return deleted;
}
[user.cs ]

屏幕

网络图库

333670/scr1.jpg

图库软件

333670/sw2.jpg

这个项目在 Github ( https://github.com/robinrizvi/Audio-Gallery-Suite ) 中持续开发,你的评论和建议和查询非常欢迎你进一步改进项目。

我希望Audio-Gallery-Suite对希望实现一个完整的音频库使用的人有用。


COM  Html5  音频  Complete  gal  Suite  
相关文章