Giter Club home page Giter Club logo

rust-mpd's Introduction

rust-mpd

Pure Rust version of libmpdclient.

Full documentation

Example

Add to Cargo.toml:

[dependencies]
mpd = "*"

Then just use:

extern crate mpd;

use mpd::Client;

let mut conn = Client::connect("127.0.0.1:6600").unwrap();
conn.volume(100).unwrap();
conn.load("My Lounge Playlist", ..).unwrap();
conn.play().unwrap();
println!("Status: {:?}", conn.status());

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

rust-mpd's People

Contributors

asamk avatar bsundsrud avatar hardfau1t avatar jakestanger avatar jistr avatar kstep avatar naglis avatar neodc avatar oberien avatar phi-gamma avatar philipp-m avatar rnestler avatar simonteixidor avatar theneikos avatar tomprince avatar wcampbell0x2a avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-mpd's Issues

Status parse error

On behalf of EatsKittens:

mpd::Client::status after a successful connexion in my situation returns:

Status: Err(Parse(BadInteger(ParseIntError { kind: InvalidDigit })))

But only if it is actually playing not when mpd is in "stop" mode. It seems to be caused by trying to parse a float track duration as integer but I'm not sure. My code used for testing this is:

extern crate mpd;

use mpd::Client;

fn main () {
	let mut client = Client::connect("localhost:6601").unwrap();
	println!("Status: {:?}", client.status());
}

Also, telnetting mpd produces:

Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
OK MPD 0.20.0
status
volume: 50
repeat: 0
random: 0
single: 0
consume: 0
playlist: 86
playlistlength: 6
mixrampdb: 0.000000
state: pause
song: 0
songid: 123
time: 0:331
elapsed: 0.000
bitrate: 320
duration: 330.556
audio: 44100:24:2
nextsong: 1
nextsongid: 124
OK

When a song is playing

Update crates.io

Looks like the last update was nearly 6 years ago! https://crates.io/crates/mpd/versions

In my crate (https://github.com/xandkar/pista-feeds) I'm currently depending directly on

mpd = { git = "https://github.com/kstep/rust-mpd.git", version = "0.1.0" }

which is preventing me from publishing it due to this version not being available in crates.io:

error: failed to prepare local package for uploading

Caused by:
  failed to select a version for the requirement `mpd = "^0.1.0"`
  candidate versions found which didn't match: 0.0.12, 0.0.11, 0.0.9, ...
  location searched: crates.io index

Adding non-existing song to queue hangs

Using latest commit from main branch with following test:

#[test]
#[should_panic(expected = "Failed to access")]
fn add_non_existing_song_returns_error() {
    let mut mpd = connect();
    let _song_id = mpd.push(Song { file: "file:///hopefully/non/existing/song.mp3".to_string(), ..Default::default() }).unwrap();
}

results in the MPD connection hanging until MPD closes the client connection due to inactivity and the returned error is Parse(BadPair).

IIUC this is caused by the read_pair() implementation introduced in 8642c72. It parses the error ACK [52@0] {addid} Failed to access /hopefully/non/existing/song.mp3: No such file or directory returned by MPD as the song ID value and then read_field hangs when waiting for expect_ok(), since there is no OK line in case of an error.

`Query` options can be used in inappropriate places.

Currently, Client::find and Client::search both accept a Query which has fields for filters, grouping, and windowing. But find and search only accept filters and windowing. I've got WIP implementations of list and findadd, the former only takes filters and grouping, the later only filters.

There are at least a couple of solutions:

  • the most straightforward is to simply split up Query into its component parts and only accept the parts that are valid for each command.
  • it'd also be possible to do something with phantom-types, but this seems more complicated for no gain.

Relicense under dual MIT/Apache-2.0

Why?

The MIT license requires reproducing countless copies of the same copyright
header with different names in the copyright field, for every MIT library in
use. The Apache license does not have this drawback, and has protections from
patent trolls and an explicit contribution licensing clause. However, the
Apache license is incompatible with GPLv2. This is why Rust is dual-licensed as
MIT/Apache (the "primary" license being Apache, MIT only for GPLv2 compat), and
doing so would be wise for this project. This also makes this crate suitable
for inclusion in the Rust standard distribution and other project using dual
MIT/Apache.

How?

To do this, get explicit approval from each contributor of copyrightable work
(as not all contributions qualify for copyright) and then add the following to
your README:

## License

Licensed under either of
 * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you shall be dual licensed as above, without any
additional terms or conditions.

and in your license headers, use the following boilerplate (based on that used in Rust):

// Copyright (c) 2015 t developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

And don't forget to update the license metadata in your Cargo.toml!

Contributor checkoff

Query: cannot move out of `query` because it is borrowed

I am trying to query the mpd server for songs, but I have a problem with the borrow checker. When I try the following code snippet, the compiler complains. In your corresponding testcase, you have commented out this part. So, how can I add filters to the query object?

Code:

extern crate mpd;

use mpd::Client;
use mpd::search::Term;
use std::env;

fn main() {
    let mut conn = Client::connect("localhost:6600").unwrap();
    let mut query = conn.query();
    query.limit(0, 2);
    let res = query.find(false, false);
    println!("{:?}", res);
}

Compiler says:

main.rs:11:15: 11:20 error: cannot move out of `query` because it is borrowed [E0505]
main.rs:11     let res = query.find(false, false);
                         ^~~~~
main.rs:10:5: 10:10 note: borrow of `query` occurs here
main.rs:10     query.limit(0, 2);

If I leave out the line query.limit(0, 2), I get an error from mpd: Err(Server(ServerError { code: Argument, pos: 0, command: "find", detail: "too few arguments for \"find\"" })). Shouldn't this return all songs?

Err(Parse(BadInteger(ParseIntError { kind: InvalidDigit })))

When using c.status() I hit this error

    extern crate mpd;

    use mpd::Client;

    fn main(){
        let mut conn = Client::connect("127.0.0.1:6600").unwrap();
        println!("{:?}", conn.status()); //  Err(Parse(BadInteger(ParseIntError { kind: InvalidDigit })))
    }

mpd --version: Music Player Daemon 0.20.6
I compiled the latest rust-mpd.

Issue with client.status()

I noticed that the tests failed locally when fetching mpd status, i.e. this:

let mut c = Client::new(TcpStream::connect("127.0.0.1:6600").unwrap()).unwrap();
println!("version: {:?}", c.version);
println!("status: {:?}", c.status());

returns:

version: Version(0, 19, 0)
status: Err(Parse(BadPair))

The problem seems to be associated with this line:

// Playback options & status {{{
/// Get MPD status
pub fn status(&mut self) -> Result<Status> {
    self.run_command("command_list_begin")
        .and_then(|_| self.run_command("status"))
        .and_then(|_| self.run_command("replay_gain_status")) // <--- here
        .and_then(|_| self.run_command("command_list_end"))
        .and_then(|_| self.read_struct())
}

as removing it solves my problem.

Tested on Arch Linux, with rust-mpd cb30c80 , Rust 1.9.0 and mpd 0.19.15.

Client::currentsong() indefinitely blocking

I just tried to use this library to query an mpd server for the current song played. However the currentsong() call blocks forever, even though the server replies correctly. I have not managed to find out why, so i am opening this issue.

Example Code:

match c.currentsong().unwrap() {
  Some(s) => {
    println!("{}", s.name.unwrap());
  },
   None => {}
}

search for song in database

search only searches for songs in the queue, as far as i can tell. is there a way to search case-insensitively for a song in the database and return all results?

lsinfo() should return a vector

The mpd lsinfo command returns a list but the return value of the corresponding client function returns a single Song. The implemented behavior returns the last entry.

The mpd documentation says: "Lists the contents of the directory URI. The response contains records starting with file, directory or playlist, each followed by metadata (tags or other metadata)."

Client::list, search, etc return type

Hi!

First, thanks for your work on rust-mpd, it makes using MPD really nice with rust :)

I am wondering though, whether it would be possible to have an iterator over Songs, Strings, etc instead of a collected Vec for search functions, such as Client::list, Client:: search, etc (for instance, here https://docs.rs/mpd/latest/mpd/client/struct.Client.html#method.list)?

Some people have very big libraries, and collecting everything into a vector tends to get out of hand.
If not, how about making a list_iter, list_search and the likes? And / or making the run_command public (and maybe all the other helper functions, since socket is private), for people who would like to experiment?

I of course don't mind making a PR, depending on what you'd prefer :)

Cheers!

listall() output is broken

As the title says.

Let's say that you runned client.listall() and you have this folder structure:

Artist1
 └─ Album1
     └─ Single1
Artist2
 └─ Album2
     └─ Single2
Artist3
 └─ Album3
     ├─ Song1
     └─ Song2

When mpd's socket list they, it looks like this:

directory: Artist1;
directory: Artist1 / Album1;
file: Artist1 / Album1 / Single1;
directory: Artist2;
directory: Artist2 / Album2;
file: Artist2 / Album2 / Single2;
directory: Artist3;
directory: Artist3 / Album3;
file: Artist3 / Album3 / Song1;
file: Artist3 / Album3 / Song2;

As you call Client::listall, it does some parsing from that output.
But when you inspect the values, rust gives you this:

[
    Song {
        file: "Artist1/Album1/Single1",
        name: None,
        title: None,
        last_mod: None,
        artist: None,
        duration: None,
        place: None,
        range: None,
        tags: [
            ("directory", "Artist2"),
            ("directory", "Artist2/Album2")
        ],
    },
    Song {
        file: "Artist2/Album2/Single2",
        ...
        tags: [
            ("directory", "Artist3"),
            ("directory", "Artist3/Album3")
        ],
    },
    Song {
        file: "Artist3/Album3/Song1",
        ...
        tags: []
    },
    Song {
        file: "Artist3/Album3/Song2",
        ...
        tags: []
    }
]
  • Every field, except file, is missing
  • The tags are shifted up

I suppose that when parsing the output, it reads every row, then when it reaches a file label, read all to the next, and join everything together. Something like:

  • Discard: directory: Artist1
  • Discard: directory: Artist1/Album1
  • Take: file: Artist1/Album1/Single1
    • Tag: directory: Artist2
    • Tag: directory: Artist2/Album2
  • Take: file: Artist2/Album2/Single2
    • Tag: directory: Artist3
    • Tag: directory: Artist3/Album3
  • Take: file: Artist3/Album3/Song1
  • Take: file: Artist3/Album3/Song2

As shown above

  • Fields are missing, this part of the code is just... missing
  • Tags are shifted, and even if not, they are wrong (in sense that every other song from that album should have it)

Looks like this project is dead, I'm leaving.

Event on idle queue triggers twice

I am trying to replicate the behaviour of the following command

while : ; do mpc idle player ; done

by using:

extern crate mpd;

use mpd::Idle;

fn main() {
    let mut conn = mpd::Client::connect("127.0.0.1:6600").unwrap();
    loop {
        let _ = conn.wait(&[mpd::Subsystem::Player]);
        println!("player");
    }
}

When I call for example mpc next the Rust variant however will often print out player twice while mpc behaves as expected.

Publishing a new minor version

Hi.
rust-lang/rust#42125 is going to turn some old compatibility "private-in-public" warnings in rustc into hard errors.
crates.io testing discovered that published version of this crate is affected by one of those errors.
The current master is building successfully with rust-lang/rust#42125, could you push it on crates.io as 0.0.12?

Error parsing status when playing DSD files

Not really sure where this problem comes from but I'll try my best to explain.

I've got a basic loop that idles in blocking mode waiting for Subsystem::Player events, matches Status.state and sets the cover on song change, or unsets it if stopped. It all goes well with other types of files, but if I start playing a DSF file I have a surge of player events and Status.state is always State::Stop. Meanwhile CPU usage goes sky high while looping through those events. Is this possibly an issue with MPD itself? How can I provide more info? Any way to clear the idle events queue?

Meanwhile mpc correctly reports state as playing

Edit: I asked if I can clear the events queue because even if I change the song to a known working one, say FLAC, MP3, whatever, I continue getting the accumulated events and state continues being matched to State::Stop.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.