parent
23663f9a11
commit
0f141119a2
@ -0,0 +1,19 @@
|
||||
##
|
||||
# radio_plus_plus
|
||||
#
|
||||
# @MakeFile
|
||||
# @version 0.1
|
||||
|
||||
all: compile install config
|
||||
|
||||
compile:
|
||||
g++ --verbose -o radio *.cpp *.h `wx-config --cxxflags --libs` -lvlc -lcurl -ljsoncpp -fgcse-after-reload -fipa-cp-clone -floop-interchange -floop-unroll-and-jam -fpeel-loops -fpredictive-commoning -fsplit-loops -fsplit-paths -ftree-loop-distribution -ftree-partial-pre -funswitch-loops -fvect-cost-model=dynamic -fversion-loops-for-strides
|
||||
|
||||
install:
|
||||
cp -v radio /usr/local/bin
|
||||
|
||||
config:
|
||||
mkdir -p ~/.config/radio++
|
||||
touch ~/.config/radio++/sender
|
||||
|
||||
# end
|
@ -1,3 +1,29 @@
|
||||
# radio_plus_plus
|
||||
# Radio ++
|
||||
### Dependencies
|
||||
> g++ \
|
||||
> wxgtk3 \
|
||||
> vlc \
|
||||
> curl \
|
||||
> jsoncpp
|
||||
|
||||
A cool c++ Internet Radio Player
|
||||
### Arch
|
||||
```
|
||||
sudo pacman -S gcc wxgtk3 vlc curl jsoncpp
|
||||
```
|
||||
|
||||
### Debian/Ubuntu
|
||||
```
|
||||
sudo apt-get install g++ libwxgtk3.0-dev libvlc-dev libcurl-dev libjsoncpp-dev
|
||||
```
|
||||
|
||||
### Gentoo GNU/Linux
|
||||
```
|
||||
doas emerge -aq jsoncpp vlc x11-libs/wxGTK-3.0
|
||||
```
|
||||
|
||||
### Installing
|
||||
```
|
||||
git clone https://github.com/MIROowo/radio_plus_plus.git
|
||||
cd radio_plus_plus
|
||||
sh compile.sh
|
||||
```
|
||||
|
@ -0,0 +1,19 @@
|
||||
g++ -o radio *.cpp *.h `wx-config --cxxflags --libs` -lvlc -lcurl -ljsoncpp
|
||||
|
||||
if [ -x ./radio ]
|
||||
then
|
||||
read -p "Do u want to install the Binary? [y/N] " input
|
||||
|
||||
if [ $input = "y" ] || [ $input = "Y" ]
|
||||
then
|
||||
mkdir -p ~/.config/radio++/
|
||||
touch ~/.config/radio++/sender
|
||||
doas cp -v radio /usr/local/bin/
|
||||
echo "Finished!"
|
||||
else
|
||||
echo "bye :c"
|
||||
fi
|
||||
else
|
||||
echo "something went wrong :/"
|
||||
echo "exit..."
|
||||
fi
|
@ -0,0 +1,220 @@
|
||||
#include "main.h"
|
||||
#include "search.h"
|
||||
|
||||
// Binding events to functions
|
||||
wxBEGIN_EVENT_TABLE(cFrame, wxFrame)
|
||||
EVT_BUTTON(1001, cFrame::OnPP)
|
||||
EVT_SLIDER(1002, cFrame::OnScroll)
|
||||
EVT_BUTTON(1003, cFrame::OnAdd)
|
||||
EVT_BUTTON(1004, cFrame::OnRemove)
|
||||
EVT_BUTTON(1005, cFrame::OnSearch)
|
||||
EVT_BUTTON(1008, cFrame::refreshEvent)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
// Window content
|
||||
cFrame::cFrame() : wxFrame(nullptr, wxID_ANY, "Radio++", wxPoint(30, 30), wxSize(450, 600)) {
|
||||
|
||||
wxFrame::SetMinSize(wxSize(450, 600));
|
||||
wxFrame::SetMaxSize(wxSize(450, 600));
|
||||
|
||||
menuBar->Append(menuHelp, "&Help");
|
||||
menuHelp->Append(wxID_ABOUT);
|
||||
menuHelp->AppendSeparator();
|
||||
menuHelp->Append(wxID_EXIT);
|
||||
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
Bind(wxEVT_MENU, &cFrame::OnAbout, this, wxID_ABOUT);
|
||||
Bind(wxEVT_MENU, &cFrame::OnExit, this, wxID_EXIT);
|
||||
|
||||
b_pp = new wxButton(this, 1001, "Play", wxPoint(10, 10), wxSize(100,50));
|
||||
t_box = new wxTextCtrl(this, wxID_ANY, "", wxPoint(10, 190), wxSize(250, 30));
|
||||
t_show = new wxStaticText(this, wxID_ANY, "None", wxPoint(10, 80), wxSize(50, 100));
|
||||
s_val = new wxStaticText(this, wxID_ANY, "70", wxPoint(150, 100), wxSize(50, 100));
|
||||
s_volume = new wxSlider(this, 1002, 70, 0, 100, wxPoint(50, 100), wxSize(220, 80));
|
||||
|
||||
b_add = new wxButton(this, 1003, "Add", wxPoint(280, 230), wxSize(80,30));
|
||||
b_add = new wxButton(this, 1004, "Remove", wxPoint(280, 270), wxSize(80,30));
|
||||
s_sender = new wxButton(this, 1005, "Search", wxPoint(280, 310), wxSize(80,30));
|
||||
b_refresh = new wxButton(this, 1008, "Refresh", wxPoint(280, 350), wxSize(80,30));
|
||||
l_sender = new wxListBox(this, wxID_ANY, wxPoint(10, 230), wxSize(250, 300));
|
||||
|
||||
// Text for the Statusbar
|
||||
CreateStatusBar();
|
||||
SetStatusText("Radio++");
|
||||
|
||||
cFrame::refreshList();
|
||||
}
|
||||
|
||||
cFrame::~cFrame() {
|
||||
}
|
||||
|
||||
void cFrame::refreshList() {
|
||||
|
||||
l_sender->Clear();
|
||||
|
||||
readfile.open(homedir+"/.config/radio++/sender");
|
||||
|
||||
if (readfile.is_open())
|
||||
{
|
||||
while ( getline (readfile,line) )
|
||||
{
|
||||
wxString wx_line(line);
|
||||
l_sender->Append(wx_line);
|
||||
}
|
||||
|
||||
readfile.close();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cFrame::refreshEvent(wxCommandEvent &evt) {
|
||||
|
||||
l_sender->Clear();
|
||||
|
||||
readfile.open(homedir+"/.config/radio++/sender");
|
||||
|
||||
if (readfile.is_open())
|
||||
{
|
||||
while ( getline (readfile,line) )
|
||||
{
|
||||
wxString wx_line(line);
|
||||
l_sender->Append(wx_line);
|
||||
}
|
||||
|
||||
readfile.close();
|
||||
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
// Get Slider Value and sets Volume
|
||||
void cFrame::OnScroll(wxCommandEvent &evt) {
|
||||
|
||||
wxString value = wxString::Format(wxT("%d"), (int)s_volume->GetValue());
|
||||
|
||||
s_val->SetLabel(value);
|
||||
int vol = wxAtoi(value);
|
||||
if (b_pp->GetLabel() == "Pause") {
|
||||
libvlc_audio_set_volume(mp, vol);
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
// Plays Radio sound yee
|
||||
void cFrame::playRadio(const char* url) {
|
||||
|
||||
sender = libvlc_media_new_location(inst, url);
|
||||
mp = libvlc_media_player_new_from_media(sender);
|
||||
libvlc_media_player_play(mp);
|
||||
}
|
||||
|
||||
|
||||
// Play/Pause Button
|
||||
void cFrame::OnPP(wxCommandEvent &evt) {
|
||||
|
||||
if(b_pp->GetLabel() == "Play") {
|
||||
|
||||
t_show->SetLabel("Playing...");
|
||||
b_pp->SetLabel("Pause");
|
||||
|
||||
std::string url = std::string(l_sender->GetStringSelection().mb_str());
|
||||
const char * c_url = url.c_str();
|
||||
|
||||
cFrame::playRadio(c_url);
|
||||
|
||||
wxString value = s_val->GetLabel();
|
||||
int vol = wxAtoi(value);
|
||||
libvlc_audio_set_volume(mp, vol);
|
||||
|
||||
} else if (b_pp->GetLabel() == "Pause") {
|
||||
|
||||
t_show->SetLabel("Paused");
|
||||
b_pp->SetLabel("Play");
|
||||
|
||||
libvlc_media_player_stop(mp);
|
||||
}
|
||||
|
||||
evt.Skip();
|
||||
|
||||
}
|
||||
// Add Button
|
||||
void cFrame::OnAdd(wxCommandEvent &evt) {
|
||||
l_sender->Append(t_box->GetValue());
|
||||
|
||||
std::string item = std::string(t_box->GetValue().mb_str());
|
||||
|
||||
writefile.open(homedir+"/.config/radio++/sender", std::ios::app);
|
||||
writefile << item << "\n";
|
||||
|
||||
writefile.close();
|
||||
|
||||
t_box->Clear();
|
||||
}
|
||||
|
||||
// Remove Button
|
||||
void cFrame::OnRemove(wxCommandEvent &evt) {
|
||||
|
||||
if (l_sender->GetSelection() != wxNOT_FOUND) {
|
||||
|
||||
std::string deleteline = std::string(l_sender->GetStringSelection().mb_str());
|
||||
|
||||
l_sender->Delete(l_sender->GetSelection());
|
||||
|
||||
// https://stackoverflow.com/questions/26576714/deleting-specific-line-from-file
|
||||
|
||||
std::string path = homedir+"/.config/radio++/sender";
|
||||
std::string tempfile = homedir+"/.config/radio++/temp.txt";
|
||||
std::string line;
|
||||
std::ifstream fin;
|
||||
|
||||
fin.open(path);
|
||||
// contents of path must be copied to a temp file then
|
||||
// renamed back to the path file
|
||||
std::ofstream temp;
|
||||
temp.open(homedir+"/.config/radio++/temp.txt");
|
||||
|
||||
while (getline(fin, line)) {
|
||||
// write all lines to temp other than the line marked for erasing
|
||||
if (line != deleteline)
|
||||
temp << line << std::endl;
|
||||
}
|
||||
|
||||
temp.close();
|
||||
fin.close();
|
||||
|
||||
// required conversion for remove and rename functions
|
||||
const char * t = tempfile.c_str();
|
||||
const char * p = path.c_str();
|
||||
remove(p);
|
||||
rename(t, p);
|
||||
}
|
||||
|
||||
evt.Skip();
|
||||
|
||||
}
|
||||
|
||||
// Search Button
|
||||
void cFrame::OnSearch(wxCommandEvent &evt)
|
||||
{
|
||||
cSearch* m_frame2 = new cSearch();
|
||||
m_frame2->Show(true);
|
||||
evt.Skip();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// OnAbout
|
||||
void cFrame::OnAbout(wxCommandEvent &evt)
|
||||
{
|
||||
wxMessageBox("By MIRO#5825",
|
||||
"About", wxOK | wxICON_INFORMATION);
|
||||
}
|
||||
|
||||
// OnExit
|
||||
void cFrame::OnExit(wxCommandEvent &evt) {
|
||||
libvlc_release (inst);
|
||||
Close(true);
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <vlc/vlc.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
|
||||
|
||||
class cFrame : public wxFrame {
|
||||
public:
|
||||
cFrame();
|
||||
~cFrame();
|
||||
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
std::string homedir = pw->pw_dir;
|
||||
|
||||
// Window content declaration
|
||||
|
||||
libvlc_media_player_t *mp;
|
||||
libvlc_media_t *sender;
|
||||
|
||||
libvlc_instance_t * inst = libvlc_new (0, NULL);
|
||||
|
||||
wxMenuBar *menuBar = new wxMenuBar;
|
||||
wxMenu *menuHelp = new wxMenu;
|
||||
|
||||
wxTextCtrl *t_box = nullptr;
|
||||
wxStaticText *t_show = nullptr;
|
||||
|
||||
wxListBox *l_sender = nullptr;
|
||||
|
||||
wxButton *b_pp = nullptr;
|
||||
wxButton *b_add = nullptr;
|
||||
wxButton *s_sender = nullptr;
|
||||
wxButton *b_refresh = nullptr;
|
||||
|
||||
wxStaticText *s_val = nullptr;
|
||||
wxSlider *s_volume = nullptr;
|
||||
|
||||
std::ifstream readfile;
|
||||
std::ofstream writefile;
|
||||
|
||||
std::string line;
|
||||
|
||||
void refreshList();
|
||||
|
||||
void refreshEvent(wxCommandEvent &evt);
|
||||
|
||||
void eraseFileLine(std::string path, std::string eraseLine);
|
||||
|
||||
void OnScroll(wxCommandEvent &evt);
|
||||
|
||||
void playRadio(const char* url);
|
||||
|
||||
void OnPP(wxCommandEvent &evt);
|
||||
|
||||
void OnAbout(wxCommandEvent &evt);
|
||||
|
||||
void OnExit(wxCommandEvent &evt);
|
||||
|
||||
void OnAdd(wxCommandEvent &evt);
|
||||
|
||||
void OnRemove(wxCommandEvent &evt);
|
||||
|
||||
void OnSearch(wxCommandEvent &evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
||||
};
|
@ -0,0 +1,95 @@
|
||||
#include "search.h"
|
||||
|
||||
wxBEGIN_EVENT_TABLE(cSearch, wxFrame)
|
||||
EVT_BUTTON(1006, cSearch::onSearch)
|
||||
EVT_BUTTON(1007, cSearch::onAdd)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
cSearch::cSearch() : wxFrame(nullptr, wxID_ANY, "Search", wxPoint(30, 30), wxSize(500, 700))
|
||||
{
|
||||
wxFrame::SetMinSize(wxSize(500, 700));
|
||||
wxFrame::SetMaxSize(wxSize(500, 700));
|
||||
|
||||
searchBox = new wxTextCtrl(this, wxID_ANY, "", wxPoint(10, 20), wxSize(300, 40));
|
||||
searchButton = new wxButton(this, 1006, "Search", wxPoint(365, 20), wxSize(80, 40));
|
||||
searchAdd = new wxButton(this, 1007, "Add", wxPoint(365, 70), wxSize(80, 40));
|
||||
searchList = new wxListBox(this, wxID_ANY, wxPoint(10, 130), wxSize(480, 500));
|
||||
|
||||
}
|
||||
|
||||
cSearch::~cSearch()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
|
||||
void cSearch::onSearch(wxCommandEvent &evt) {
|
||||
|
||||
searchList->Clear();
|
||||
|
||||
wxString boxValue(searchBox->GetValue());
|
||||
std::string api = "https://api.laut.fm/search/stations?query=" + std::string(boxValue.mb_str());
|
||||
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
std::string readBuffer;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
curl_easy_setopt(curl, CURLOPT_URL, api.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
bool j_parse = jread.parse(readBuffer, jval, false);
|
||||
|
||||
if (j_parse) {
|
||||
|
||||
Json::Value arrays = jval["results"][0]["items"];
|
||||
|
||||
int arraynum = arrays.size();
|
||||
|
||||
|
||||
for (int i = 0; i < arraynum; i++)
|
||||
{
|
||||
std::string name = fastWriter.write(jval["results"][0]["items"][i]["station"]["stream_url"]);
|
||||
searchList->Append(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void cSearch::onAdd(wxCommandEvent &evt)
|
||||
{
|
||||
if (searchList->GetSelection() != wxNOT_FOUND)
|
||||
{
|
||||
std::string item = std::string(searchList->GetStringSelection());
|
||||
|
||||
item.erase(0, 1);
|
||||
|
||||
int start{item.length()-2};
|
||||
int end{item.length()-1};
|
||||
|
||||
item.erase(start, end);
|
||||
|
||||
std::ofstream writefile;
|
||||
|
||||
writefile.open(homedir+"/.config/radio++/sender", std::ios::app);
|
||||
writefile << item << "\n";
|
||||
writefile.close();
|
||||
|
||||
|
||||
}
|
||||
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
#include <wx/wx.h>
|
||||
#include <curl/curl.h>
|
||||
#include <json/json.h>
|
||||
#include <json/value.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
class cSearch : public wxFrame {
|
||||
public:
|
||||
cSearch();
|
||||
~cSearch();
|
||||
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
std::string homedir = pw->pw_dir;
|
||||
|
||||
Json::FastWriter fastWriter;
|
||||
Json::Reader jread;
|
||||
Json::Value jval;
|
||||
|
||||
wxTextCtrl *searchBox = nullptr;
|
||||
wxButton *searchButton = nullptr;
|
||||
wxButton *searchAdd =nullptr;
|
||||
|
||||
wxListBox *searchList = nullptr;
|
||||
|
||||
void onSearch(wxCommandEvent &evt);
|
||||
|
||||
void onAdd(wxCommandEvent &evt);
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
#include "window.h"
|
||||
#include "main.h"
|
||||
|
||||
wxIMPLEMENT_APP(cWindow);
|
||||
|
||||
cWindow::cWindow() {
|
||||
|
||||
}
|
||||
|
||||
cWindow::~cWindow() {
|
||||
|
||||
}
|
||||
|
||||
// GUI Init
|
||||
bool cWindow::OnInit() {
|
||||
|
||||
m_frame1 = new cFrame();
|
||||
m_frame1->Show(true);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in new issue