Linux项目:音乐播放器
文章目录
- 1.项目介绍
- 2.前端代码
- 1.httplib快速搭建一个http服务器
- 2.B/S双方的数据交互选择JSON数据格式,http请求和响应的正文中采用jsoncpp开源库
- 3.前段的js代码向发送ajax请求
- 三、服务端代码
- 1.搭建一个music_player这样的一个类
- 2.增加注册按钮,并且点击注册按钮跳转到注册界面
- 3.服务端代码当中调用mysql-c api连接数据库,进行操作
- 4.登录查询用户是否存在校验邮箱和密码
- 5.通过命令行参数获取ip地址和端口号信息
- 6.保存登录的会话信息session,使用md5摘要保护登录信息,否则造成直接跳转list.html界面
- 7.用哈希表保存多个用户的信息
- 8.数据库存放音乐相关信息,通过json串返回给浏览器
- 9.查询音乐、喜欢的音乐、添加喜欢的音乐
1.项目介绍
音乐播放器拥有注册登录功能,查看所有的音乐列表,也可以听音乐,也可以将音乐添加到自己的喜欢列表。
2.前端代码
1.httplib快速搭建一个http服务器
1 #include<stdio.h>2 #include<iostream>3 4 #include<string.h>5 #include"httplib.h"6 7 using namespace httplib;8 using namespace std;9 10 int g_val=100;11 12 void Get_CallBackFunc(const Request& req, Response& resp)13 {14 printf("%d\n",g_val);15 cout<<req.method<<endl;16 printf("i am Get_CallBackFunc\n");17 18 const char* lp="<html><h2>hello world!</h2></html>";19 resp.set_content(lp,strlen(lp),"text/html");20 }21 22 23 24 int main()25 {26 Server http_svr;27 int a=10;28 29 http_svr.Get("/abc",Get_CallBackFunc);30 http_svr.Post("/111",[a](const Request& req,Response& resp){31 printf("a:%d\n",a);32 33 });34 //直接访问web里面的文件35 //逻辑根目录指定为web文件夹36 http_svr.set_mount_point("/","./web");37 http_svr.listen("0.0.0.0",21010);38 39 return 0;40 }
2.B/S双方的数据交互选择JSON数据格式,http请求和响应的正文中采用jsoncpp开源库
1 #include<stdio.h>2 #include<iostream>3 #include<jsoncpp/json/json.h>4 5 using namespace std;6 7 int main()8 {9 10 Json::Value v1;11 v1["id"]=1;12 v1["name"]="yyw";13 cout<<v1<<endl;14 15 Json::Value v2;16 v2["id"]=2;17 v2["name"]="yy";18 cout<<v2<<endl;19 20 Json::Value v3;21 v3["v1"]=v1;22 v3["v2"]=v2;23 cout<<v3<<endl;24 25 Json::Value v4;26 v4.append(v1);27 v4.append(v2);28 cout<<v4<<endl;29 30 for(int i=0;i<2;i++)31 {32 cout<<v4[i]["id"]<<":"<<v4[i]["name"]<<endl;33 }34 35 //序列化36 Json::FastWriter w;37 string json_str=w.write(v4);38 cout<<json_str<<endl;39 //反序列化40 Json::Reader r;41 Json::Value vv;42 r.parse(json_str,vv);43 cout<<vv<<endl;44 return 0;45 }
JSON数据格式有三种显示方法:平铺、嵌套、数组形式。
序列化和反序列化:
3.前段的js代码向发送ajax请求
#include<stdio.h>
#include<iostream>#include<jsoncpp/json/json.h>
#include<string.h>
#include"httplib.h"using namespace httplib;
using namespace std;int g_val=100;void Get_CallBackFunc(const Request& req, Response& resp)
{printf("%d\n",g_val);cout<<req.method<<endl;printf("i am Get_CallBackFunc\n");const char* lp="<html><h2>hello world!</h2></html>";resp.set_content(lp,strlen(lp),"text/html");
}int main()
{Server http_svr;http_svr.Get("/abc",Get_CallBackFunc);//发送post请求/login,回调这个表达式http_svr.Post("/login",[](const Request& req,Response& resp){cout<<req.body<<endl; //打印正文信息Json::Value resp_json;resp_json["login_status"]=true; //浏览器返回登录状态//序列化//系列化成完整的字符串的内容放到响应的正文中Json::FastWriter w;resp.body= w.write(resp_json);//告诉浏览器返回的内容就是json串,对json解析resp.set_header("Content-Type","application/json");});//直接访问web里面的文件//逻辑根目录指定为web文件夹http_svr.set_mount_point("/","./web");http_svr.listen("0.0.0.0",21010);return 0;
}
三、服务端代码
1.搭建一个music_player这样的一个类
1 #pragma once2 #include"database.hpp"3 #include<stdio.h>4 #include<iostream>5 #include<string>6 #include"httplib.h"7 8 #include<jsoncpp/json/json.h>9 10 using namespace std;11 12 using namespace httplib;13 14 #define MUSIC_SVR_IP "0.0.0.0"15 #define MUSIC_SVR_PORT 1898916 17 class MusicServer18 {19 public:20 MusicServer()21 {22 svr_ip_=MUSIC_SVR_IP;23 svr_port_=MUSIC_SVR_PORT;24 db_svr_=NULL;25 }26 ~MusicServer()27 {28 29 }30 31 //1.初始化当前类接32 int InitMusicServer(string ip=MUSIC_SVR_IP,uint16_t port=MUSIC_SVR_PORT)33 {34 svr_ip_=ip;35 svr_port_=port;36 37 db_svr_=new DataBaseSvr("1.14.165.138","yy","123","music_svr");38 if(db_svr_==NULL)39 {40 return -1;41 }42 return 0;43 }44 //2.启动服务的接口45 int StartMusicServer()46 {47 //1.注册个若干个http请求的对应的回调函数48 /*49 *请求:{"name":"yy","passwd":"123","email":"123@qq.com","phonenum":"1231"}50 *响应:{"register_status":"xxxx"}51 *52 *53 * */54 http_svr_.Post("/register",[this](const Request& req,Response& resq){55 cout<<req.body<<endl;56 //1.需要将浏览器中的数据持久化(保存在数据库中) 57 //58 //1.将用户提交的数据进行反序列化,拿到一个json对象59 Json::Reader r;60 Json::Value v;61 r.parse(req.body,v);62 63 cout<<v["name"]<<endl;64 cout<<v["passwd"]<<endl;65 cout<<v["email"]<<endl;66 cout<<v["phonenum"]<<endl;67 68 db_svr_->InsertUserInfo(v);69 });70 71 http_svr_.Post("/login",[](const Request& req,Response& resq){72 /*73 *1.74 *2.75 *3.76 * */77 cout<<req.body<<endl;78 79 });80 81 //2.设置http服务器静态路径(逻辑根目录)82 http_svr_.set_mount_point("/","./web");83 //3.监听起来84 http_svr_.listen(svr_ip_.c_str(),svr_port_);85 }86 private:87 //httplib 当中的server对象88 Server http_svr_;89 90 string svr_ip_;91 uint16_t svr_port_;92 93 //数据库操作模块94 DataBaseSvr* db_svr_;95 };
2.增加注册按钮,并且点击注册按钮跳转到注册界面
54 http_svr_.Post("/register",[this](const Request& req,Response& resq){55 cout<<req.body<<endl;56 //1.需要将浏览器中的数据持久化(保存在数据库中) 57 //58 //1.将用户提交的数据进行反序列化,拿到一个json对象59 Json::Reader r;60 Json::Value v;61 r.parse(req.body,v);62 63 cout<<v["name"]<<endl;64 cout<<v["passwd"]<<endl;65 cout<<v["email"]<<endl;66 cout<<v["phonenum"]<<endl;67 68 db_svr_->InsertUserInfo(v);69 });
3.服务端代码当中调用mysql-c api连接数据库,进行操作
1 #pragma once2 #include<stdio.h>3 #include<unistd.h>4 #include<iostream>5 #include<string>6 7 #include<mysql/mysql.h>8 #include<jsoncpp/json/json.h>9 using namespace std;10 class DataBaseSvr11 {12 public:13 DataBaseSvr(const string& db_host,const string& db_user,const string& db_password,const string& db_name,unsigned int db_port=3306)14 {15 mysql_init(&mysql_);16 db_host_=db_host;17 db_user_=db_user;18 db_password_=db_password;19 db_port_=db_port;20 db_name_=db_name;21 }22 ~DataBaseSvr()23 {24 25 }26 27 int ConnectToMysql()28 {29 if(!mysql_real_connect(&mysql_,db_host_.c_str(),db_user_.c_str(),db_password_.c_str(),db_name_.c_str(),db_port_,NULL,CLIENT_FOUND_ROWS))30 {31 cout<<mysql_error(&mysql_)<<endl;32 return -1;33 }34 return 0;35 }36 37 //提交上来的对象38 int InsertUserInfo(const Json::Value& v)39 {40 //1.连接数据库41 if(ConnectToMysql()<0)42 {43 return -1;44 }45 //2.组织sql语46 47 string name=v["name"].asString();48 string password=v["password"].asString();49 string email=v["email"].asString();50 string phonenum=v["phonenum"].asString();51 52 #define INSERT_USER_INFO "insert into sys_user(user_name,password,email,phone_num) values('%s','%s','%s','%s');"53 54 char sql[1024]={0};55 snprintf(sql,sizeof(sql)-1,INSERT_USER_INFO,name.c_str(),password.c_str(),email.c_str(),phonenum.c_str());56 cout<<"sql:"<<sql<<endl;57 58 //3.继续执行sql59 //4.返回插入结果给调用者60 }61 private:62 MYSQL mysql_;63 64 string db_host_;65 string db_user_;66 string db_password_;67 string db_name_;68 unsigned int db_port_;69 };
4.登录查询用户是否存在校验邮箱和密码
//查询用户是否存在105 int QueryUserExist(const Json::Value& v)106 {107 /* //0 链接108 if(ConnectToMysql()<0)109 {110 return -1;111 }*/112 //1.从json对象当中解析出来 邮箱和密码113 114 string email = v["email"].asString();115 string password = v["password"].asString();116 117 //2.使用邮箱作为查询条件在sys_user表当中进行查询(如果没有查找到用户,则返回)118 #define QUERY_USER "select * from sys_user where email='%s';"119 char sql[1024] = {0};120 snprintf(sql, sizeof(sql) - 1, QUERY_USER, email.c_str());121 cout << sql << endl;122 123 //3.针对查询的结果当中的密码, 进行比对124 MYSQL_RES* res = NULL;125 if(ExecuteSql(sql, &res) == false)126 {127 return -2;128 }129 130 //3.1 针对结果集进行操作, 判断下,结果集当中的行数是否等于1131 // 等于1, 继续往下执行132 // 不等1 , 直接返回133 //my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);134 if(mysql_num_rows(res) != 1)135 {136 cout << "No Data for sql!, sql is " << sql <<endl;137 mysql_free_result(res);138 return -3;139 }140 141 //3.2 在结果集当中获取一行数据142 //MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result);143 // 如果重复调用msyql_fetch_row这个函数, 默认是取下一行的数据144 MYSQL_ROW row = mysql_fetch_row(res);145 146 //3.3 比对密码147 string db_password = row[2];148 if(db_password != password )149 {150 return -4;151 }152 153 mysql_free_result(res);154 //4.返回查询结果155 return atoi(row[0]); 156 }
5.通过命令行参数获取ip地址和端口号信息
1 #include"music_player.hpp"2 void Usage()3 {4 cout << "./MusicServer [command key] [command value] ..." << endl;5 cout << " " << "-ip : svr listen ip" << endl;6 cout << " " << "-port : svr listen port" << endl;7 cout << " " << "-db_ip : msyql server ip address" << endl;8 cout << " " << "-db_port : mysql port" << endl;9 cout << " " << "-db_user : mysql user" << endl;10 cout << " " << "-db_passwd : mysql password" << endl;11 cout << " " << "-db_db : which database " << endl;12 cout << " " << "-h : show usage" << endl;13 }14 15 //通过命令行参数获取ip地址和端口号之类的信息16 int main(int argc, char* argv[])17 {18 if(argc == 2 && strcmp(argv[1], "-h") == 0)19 {20 Usage();21 exit(1);22 }23 string svr_ip, db_ip, db_user, db_db, db_passwd;24 uint16_t svr_port, db_port;25 for(int i = 0; i < argc; i++)26 {27 if(strcmp(argv[i], "-ip") == 0 && i + 1 < argc)28 {29 svr_ip = argv[i + 1];30 }31 else if(strcmp(argv[i], "-port") == 0 && i + 1 < argc)32 {33 svr_port = atoi(argv[i + 1]);34 }35 else if(strcmp(argv[i], "-db_ip") == 0 && i + 1 < argc)36 {37 db_ip = argv[i + 1];38 }39 else if(strcmp(argv[i], "-db_port") == 0 && i + 1 < argc)40 {41 db_port = atoi(argv[i + 1]);42 }43 else if(strcmp(argv[i], "-db_user") == 0 && i + 1 < argc)44 {45 db_user = argv[i + 1];46 }47 else if(strcmp(argv[i], "-db_db") == 0 && i + 1 < argc)48 {49 db_db = argv[i + 1];50 }51 else if(strcmp(argv[i], "-db_passwd") == 0 && i + 1 < argc)52 {53 db_passwd = argv[i + 1];54 }55 }56 cout<<"please check info:"<<endl;57 cout << "svr_ip: " << svr_ip << endl;58 cout << "svr_pot: " << svr_port << endl;59 cout << "db_ip: " << db_ip << endl;60 cout << "db_port: " << db_port << endl;61 cout << "db_user: " << db_user << endl;62 //cout << "db_passwd: " << db_passwd << endl;63 cout << "db_db: " << db_db << endl;64 65 //重新输出ip66 int select = 0;67 cout << "enter check result: currect input 1, error input 0;" << endl;68 cout << "[input select]: ";69 cin >> select;70 switch(select)71 {72 case 0:73 cout << "plase retry start server.." << endl;74 break;75 case 1:76 {77 MusicServer* ms = new MusicServer();78 if(ms == NULL)79 {80 return -1;81 }82 83 if(ms->InitMusicServer(db_ip, db_port, db_user, db_passwd, db_db, svr_ip, svr_port) < 0)84 {85 return -2;86 }87 ms->StartMusicServer();88 delete ms;89 break;90 }91 default:92 printf("input select num error, please input 1(currect) or 0(error)\n");93 break;94 }95 96 return 0;97 }
6.保存登录的会话信息session,使用md5摘要保护登录信息,否则造成直接跳转list.html界面
1 #pragma once2 #include <stdio.h>3 #include <unistd.h>4 #include <string.h>5 #include <openssl/md5.h>6 #include <iostream>7 #include <string>8 #include <unordered_map>9 10 #include <jsoncpp/json/json.h>11 #include "httplib.h"12 13 using namespace std;14 using namespace httplib;15 16 typedef enum UserStatus17 {18 //不在线19 OFFLINE = 0,20 //在线状态21 ONLINE,22 }USER_STATUS;23 24 25 //针对与登录的用户创建的会话信息26 27 class Session28 {29 public:30 Session()31 {32 33 }34 35 Session(const Json::Value& v, int user_id)36 {37 user_id_ = user_id;38 39 real_str_ += v["email"].asString();40 real_str_ += v["password"].asString();41 42 us_status_ = ONLINE;43 }44 45 ~Session()46 {47 48 }49 50 51 bool CalcMd5()52 {53 MD5_CTX ctx;54 MD5_Init(&ctx);55 56 //int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);57 if(MD5_Update(&ctx, real_str_.c_str(), real_str_.size()) != 1)58 {59 return false;60 }61 62 //int MD5_Final(unsigned char *md, MD5_CTX *c);63 //md ==> 16字节64 unsigned char md5[16] = { 0 };65 if(MD5_Final(md5, &ctx) != 1)66 {67 return false;68 }69 70 char tmp[2] = {0};71 char buf[32] = {0};72 for(int i = 0; i < 16; i++)73 {74 sprintf(tmp, "%02x", md5[i]);75 strncat(buf, tmp, 2);76 }77 78 session_id_ = buf;79 cout << "session_id_" << session_id_ << endl;80 return true;81 }82 83 string& GetSessionID()84 {85 //1.计算sessionID86 CalcMd5();87 //2.返回session_id88 return session_id_;89 }90 91 int GetUserId()92 {93 return user_id_;94 }95 96 private:97 string session_id_;98 99 //生成会话ID的源字符串100 string real_str_;101 102 int user_id_;103 104 UserStatus us_status_;105 };
7.用哈希表保存多个用户的信息
107 //哈希查找多用户的时刻更快108 class AllSessionInfo109 {110 public:111 AllSessionInfo()112 {113 all_sess_map_.clear();114 pthread_mutex_init(&map_lock_, NULL);115 }116 117 ~AllSessionInfo()118 {119 pthread_mutex_destroy(&map_lock_);120 }121 122 void InsertSessionInfo(const string session_id, const Session sess)123 {124 pthread_mutex_lock(&map_lock_);125 all_sess_map_.insert(make_pair(session_id, sess));126 pthread_mutex_unlock(&map_lock_);127 }128 129 int CheckSession(const Request& req)130 {131 /*132 * 1.通过http请求头当中的 Cookie字段, 获取对应的value(会话ID)133 * 2.通过会话ID, 在all_sess_map_当中查找, 是否有对应的会话信息134 * */135 string sess_id = req.get_header_value("Cookie");136 137 pthread_mutex_lock(&map_lock_);138 auto iter = all_sess_map_.find(sess_id);139 if(iter == all_sess_map_.end())140 {141 pthread_mutex_unlock(&map_lock_);142 return -1;143 }144 int user_id = iter->second.GetUserId();145 pthread_mutex_unlock(&map_lock_);146 return user_id;147 }148 private:149 unordered_map<string, Session> all_sess_map_;150 pthread_mutex_t map_lock_;151 };
8.数据库存放音乐相关信息,通过json串返回给浏览器
int GetMusic(string sql, Json::Value& resp_json)161 {162 MYSQL_RES* res = NULL;163 if(ExecuteSql(sql, &res) == false)164 {165 return -2;166 }167 168 int row_nums = mysql_num_rows(res);169 if(row_nums <= 0)170 {171 printf("No data: sql is \"%s\"", sql.c_str());172 mysql_free_result(res);173 return -3;174 }175 176 MYSQL_ROW row = mysql_fetch_row(res);177 Json::Value music_value;178 while(row != NULL)179 {180 //1.保存数据到json当中181 Json::Value tmp;182 tmp["id"] = row[0];183 tmp["title"] = row[1];184 tmp["singer"] = row[2];185 tmp["url"] = row[3];186 187 music_value.append(tmp);188 row = mysql_fetch_row(res);189 }190 191 resp_json["music"] = music_value;192 mysql_free_result(res);193 return 0;194 }195 196 197 int GetAllMusic(Json::Value& resp_json)198 {199 /*200 * 1.组织查询的sql语句201 * 2.调用ExecuteSql函数执行sql语句202 * 3.检查结果集当中的行数203 * 4.将获取到的结果集, 进行遍历操作204 * 4.组织json对象205 * */206 const char* sql = "select * from music;";207 return GetMusic(sql, resp_json);208 }209 210 211 212 int InsertLoveMusic(const Request& req, int user_id)213 {214 /*215 * 1.通过req当中的正文信息, 获取music_id216 * 2.使用music_id, user_id组织sql语句217 * 3.执行sql语句218 * */219 Json::Reader r;220 Json::Value v;221 r.parse(req.body, v);222 223 int music_id = v["music_id"].asInt();224 225 #define INSERT_LOVE_MUSIC "insert into love_music(user_id, music_id) values(%d, %d);"226 char sql[1024] = {0};227 snprintf(sql, sizeof(sql) - 1, INSERT_LOVE_MUSIC, user_id, music_id);228 229 if(ExecuteSql(sql) == false)230 {231 return -1;232 }233 return 1;234 }235 236 int GetLoveMusic(int user_id, Json::Value& resp_json)237 {238 /*239 * 1.组织查询sql240 * 2.调用GetMusic函数241 * */242 #define GET_LOVE_MUSIC "select * from music where music_id in(select music_id from love_music where user_id=%d);"243 char sql[1024] = {0}; 244 snprintf(sql, sizeof(sql) - 1, GET_LOVE_MUSIC, user_id);245 return GetMusic(sql, resp_json);246 }
9.查询音乐、喜欢的音乐、添加喜欢的音乐
http_svr_.Get("/findMusic", [this](const Request& req, Response& resp){137 /*138 * 1.会话校验, 从当前http请求的请求体当中拿到 Cookie对应的value值, 会话ID139 * 1.1 通过会话ID, 在all_sess_当中查找是否有对应的会话140 * 找到了, 则认为该用户是登录用户, 就可以做后续查找音乐的操作141 * 没有找到, 则认为该用户是非登录用户, 则返回status为-1142 * 2.通过数据库模块在数据表music当中查找音乐信息, 则将查找到的音乐信息组织成为json串143 * 3.组织应答144 * */145 Json::Value resp_json;146 int user_id = all_sess_->CheckSession(req);147 resp_json["status"] = user_id;148 if(user_id > 0)149 {150 /* 1.会话校验成功的逻辑151 * 2.访问数据库, 获取到数据表music的音乐信息152 */153 db_svr_->GetAllMusic(resp_json); 154 }155 156 Json::FastWriter w;157 resp.body = w.write(resp_json);158 resp.set_header("Content-Type", "application/json");159 }); 160 161 http_svr_.Post("/loveMusic", [this](const Request& req, Response& resp){162 Json::Value resp_json;163 int user_id = all_sess_->CheckSession(req);164 resp_json["status"] = user_id;165 if(user_id > 0)166 {167 cout << "user_id: " << user_id << ", req正文信息:" << req.body << endl;168 resp_json["status"] = db_svr_->InsertLoveMusic(req, user_id);169 }170 171 Json::FastWriter w;172 resp.body = w.write(resp_json);173 resp.set_header("Content-Type", "application/json");174 });175 176 http_svr_.Get("/findLoveMusic", [this](const Request& req, Response& resp){177 /*178 * 1.会话校验,通过会话校验, 如果成功就能获取当前请求的用户ID179 * 2.查数据库, 当前用户喜欢的音乐180 * 3.组织json, 将用户喜欢的音乐返回给浏览器181 * */182 Json::Value resp_json;183 int user_id = all_sess_->CheckSession(req);184 resp_json["status"] = user_id;185 if(user_id > 0)186 {187 //去数据库当中查询喜欢的音乐188 db_svr_->GetLoveMusic(user_id, resp_json);189 }190 191 Json::FastWriter w;192 resp.body = w.write(resp_json);193 resp.set_header("Content-Type", "application/json");194 }); 195 //2.设置http服务器静态路径(逻辑根目录)196 http_svr_.set_mount_point("/","./web");197 //3.监听起来198 http_svr_.listen(svr_ip_.c_str(),svr_port_);199 }
Linux项目:音乐播放器相关推荐
- 微信小程序练手项目-音乐播放器
微信小程序练手项目-音乐播放器 该项目只适合练手,大佬请绕道 项目展示图: 项目介绍 微信小程序音乐播放器 页面: 音乐推荐.播放器.播放列表 功能: 播放.暂停.上一首.下一首.跳转播放列表.实时进 ...
- Java web项目——音乐播放器
Java web项目--音乐播放器 1,需求分析 ①登录并查看自己的音乐列表 ②从本地上传音乐 ③删除某个音乐 ④删除选中的音乐 ⑤查询音乐(支持模糊查询) ⑥添加音乐到喜欢列表且可进行移除 ⑦可在喜 ...
- 基于嵌入式linux的音乐播放器设计,基于嵌入式Linux的多媒体音乐播放器的设计与实现...
中图分类号:TP316.5 文献标识码:A 文章编号:1009-2552(2009)06-0102-03 基于嵌入式Linux的多媒体音乐播放器的设计与实现 王 奇 (黑龙江八一农垦大学信息技术学院, ...
- linux播放器安装程序,Linux下音乐播放器Audacious 3.10下载与安装
一款Linux下的音乐播放器Audacious 3.10正式发布下载了,它带来了新的功能和一些重要改进,尽管Audacious 4.0(具有功能齐全的 Qt UI)还没有开发出来,但他们也没有闲着,代 ...
- linux终端音乐播放器,Linux终端音乐播放器cmus攻略: 操作歌单
cmus是一款开源的终端音乐播放器.它小巧快速,而又功能强大.cmus支持Ogg/Vorbis.MP3.FLAC.Musepack.WavPack.WMA.WAV.AAC.MP4等格式,包含Gaple ...
- linux qt4 音乐播放器,Ubuntu 14.04下安装音乐播放器 Clementine 1.2.3
Clementine 是一款非常不错的自由开源音乐播放器,支持很多国外的云空间,比如box.com.Clementine使用qt4编写,灵感来自Amarok 1.4.Clementine还是一款跨平台 ...
- 个人项目——音乐播放器(一)
1 功能需求及技术可行性分析 1.1编写目的 现今社会生活紧张,而欣赏音乐史其中最好的舒缓压力的方式之一,音乐播放类的软 件数不胜数,为什么我还要再写一个播放器出来呢?因为现有的音乐播放器功能实在 ...
- linux 中文 音乐播放器,linux下的常见音乐播放器
xmms 老牌的音乐播放器,模仿Windows下*的播放器Winamp,其强大的功能不输于Winamp,具有极强的可扩展性,支持mp3.ogg.wav等格式播放,添加插件后还可以播放AAC.wma等格 ...
- WEB项目-音乐播放器
音乐播放器 需求分析 数据库设计 实体类 Dao层 Servlet层 补充 需求分析 1.注册登陆 使用post请求,登陆路径为/login,传输的数据为username,password,这里就使用 ...
最新文章
- 打破定式,突破屏障,走出自己的创意舒适区
- 【Android 进程保活】Android 进程优先级 ( 前台进程 | 可见进程 | 服务进程 | 后台进程 | 空进程 )
- easyui表单网格列错位_《HTML5从入门到精通》——第3章 HTML表格与表单
- Tkinter的Scrollba组件
- 想转行人工智能?机会来了!
- java公平索非公平锁_java中的非公平锁不怕有的线程一直得不到执行吗
- 前端学习(1316):静态资源
- Python学习笔记:使用Python操作数据库
- swift版本hello
- 50阶乘c语言思想,求10000的阶乘(c语言代码实现)
- maven(二) maven项目构建ssh工程(父工程与子模块的拆分与聚合)
- linux下电子词典里的扩展存储卡不能访问到的问题
- 磁盘驱动器号的修改恢复
- 内蒙古自治区及其盟市行政单位中英文名称对照表
- win10忘记账户密码完美解决方案
- c语言实现小球跳动的效果
- 奇迹服务器数据修改,奇迹Mu商业服务端 客户端装备外观修改说明!
- edge浏览器添加新标签页问题
- 当老师退出伽卡他卡教师端,但是还没下课时,程序一直提示连接失败真的很烦,下面和大家分享一下怎么退出伽卡他卡
- 如何使用图片的exif信息计算相机焦距