I'm trying to use librespot for my own little project. Actually, I've been using it for almost a year now. Yet, I'm a total noob when it comes to Rust... And today I'm stuck. Here's what I'm trying to do.
My application is based on librespot's sample main.rs. But I'd like to expand its event signaling mechanism to do a http request to my server, rather than run some shell script. For this I want to replace the call to its event handler with my own.
I actually had something running. But it seems my method should never have worked. I'm running a core loop inside another core loop. Here's my event handler, which is called from main's loop: https://github.com/michaelherger/spotty/blob/f3136f40c9ecee3ba5de2c20fd75ba20312b9867/src/lms.rs#L127 .
Something has changed in Rust recently, because now I'm getting a crash 'cannot recursively call into Core
'.
So... I'm trying to get rid of this. I understand I should pass the handle from main to the event handler, which in turn should return a future(?). But that's where I'm stuck. Once I have the hyper::Request
, what would I need to do with it in order to have it processed?
1 Like
Hopefully I can paste the stack trace here... wasn't allowed to do so in my very first posting :-).
DEBUG:librespot_connect::discovery: Zeroconf server listening on 0.0.0.0:0
WARN:mdns: Failed to register IPv6 receiver: Error { repr: Os { code: 49, message: "Can\'t assign requested address" } }
INFO:librespot_core::session: Connecting to AP "...."
INFO:librespot_core::session: Authenticated as "username" !
DEBUG:librespot_core::session: new Session[0]
DEBUG:librespot_connect::spirc: new Spirc[0]
DEBUG:librespot_core::mercury: new MercuryManager
DEBUG:librespot_playback::player: new Player[0]
DEBUG:librespot_connect::spirc: linear volume: 32768
DEBUG:librespot_playback::player: command=Volume(32768)
INFO:spotty::lms: volume 50
INFO:spotty::lms: Base URL to talk to LMS:
INFO:spotty::lms: Player MAC address to control: ac:bc:de:ef:ae:d1
INFO:spotty::lms: Command to send to player: ["spottyconnect","volume",50]
thread 'main' panicked at 'cannot recursively call into `Core`', src/libcore/option.rs:839:4
stack backtrace:
0: 0x10e18ec83 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::h6f26156f36f91c7c
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: 0x10e18b070 - std::sys_common::backtrace::_print::h0b677b64a478c8cb
at src/libstd/sys_common/backtrace.rs:69
2: 0x10e1913b3 - std::panicking::default_hook::{{closure}}::h2a99d1ab84807307
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:381
3: 0x10e1910b2 - std::panicking::default_hook::h540d2e3ab8360bf0
at src/libstd/panicking.rs:397
4: 0x10e1918c2 - std::panicking::begin_panic::had0530100710df8d
at src/libstd/panicking.rs:577
5: 0x10e1917a4 - std::panicking::begin_panic::had0530100710df8d
at src/libstd/panicking.rs:538
6: 0x10e191672 - std::panicking::try::do_call::hab1a42132be4fc65
at src/libstd/panicking.rs:522
7: 0x10e1915da - std::panicking::try::do_call::hab1a42132be4fc65
at src/libstd/panicking.rs:498
8: 0x10e1c97c3 - <core::ops::range::Range<Idx> as core::fmt::Debug>::fmt::h1d8acafc4a3cbc3f
at src/libcore/panicking.rs:71
9: 0x10e1c982d - <core::ops::range::Range<Idx> as core::fmt::Debug>::fmt::h1d8acafc4a3cbc3f
at src/libcore/option.rs:839
10: 0x10d2cf5de - <core::option::Option<T>>::expect::h568c6a1f9319294d
at /Users/travis/build/rust-lang/rust/src/libcore/option.rs:302
11: 0x10d3096eb - tokio_core::reactor::Core::run::h3c136aa2f0b23607
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.16/src/reactor/mod.rs:242
12: 0x10d2feefc - spotty::lms::LMS::request::h58e1a73788dd0f1a
at src/lms.rs:127
13: 0x10d2fe2e9 - spotty::lms::LMS::volume::h62989f587ef99ecf
at src/lms.rs:88
14: 0x10d2fdf41 - spotty::lms::LMS::signal_event::h2beaaa282b622e07
at src/lms.rs:63
15: 0x10d32ed79 - <spotty::Main as futures::future::Future>::poll::h135eed544ada837f
at src/main.rs:407
16: 0x10d2ee31c - <futures::task_impl::Spawn<T>>::poll_future_notify::{{closure}}::ha0b1760bde4e70cf
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:289
17: 0x10d2efaef - <futures::task_impl::Spawn<T>>::enter::{{closure}}::h7a7edb91880ae51b
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:363
18: 0x10d3277d6 - futures::task_impl::std::set::h1b8f65c32b486fba
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/std/mod.rs:78
19: 0x10d2ef75e - <futures::task_impl::Spawn<T>>::enter::ha37fd360b116b996
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:363
20: 0x10d2ede24 - <futures::task_impl::Spawn<T>>::poll_future_notify::h9015bee84dac9ab9
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:289
21: 0x10d30c042 - tokio_core::reactor::Core::run::{{closure}}::{{closure}}::{{closure}}::{{closure}}::hf7ea3b21e064094e
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.16/src/reactor/mod.rs:253
22: 0x10d2f0d77 - <futures::future::lazy::Lazy<F, R>>::get::h7c9dbfcb5471b096
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/future/lazy.rs:64
23: 0x10d2fa79c - <futures::future::lazy::Lazy<F, R> as futures::future::Future>::poll::hfc31a298d4a2224a
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/future/lazy.rs:82
24: 0x10d2ee53c - <futures::task_impl::Spawn<T>>::poll_future_notify::{{closure}}::hd5cabfcdce8feaf3
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:289
25: 0x10d2efc2f - <futures::task_impl::Spawn<T>>::enter::{{closure}}::hb9b0a13b0d594109
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:363
26: 0x10d328535 - futures::task_impl::std::set::hf6e2eec73297f039
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/std/mod.rs:78
27: 0x10d2eee9e - <futures::task_impl::Spawn<T>>::enter::h3c60b933659689e1
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:363
28: 0x10d2edeb4 - <futures::task_impl::Spawn<T>>::poll_future_notify::hb4cc9fc85aecccbc
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.21/src/task_impl/mod.rs:289
29: 0x10d2b78ef - <tokio::executor::current_thread::Entered<'a, P>>::block_on::{{closure}}::h6d0e38dbd523c1b1
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.1.6/src/executor/current_thread/mod.rs:464
30: 0x10d2b64da - <tokio::executor::current_thread::Borrow<'a, U>>::enter::{{closure}}::{{closure}}::h0cc1a3401a330566
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.1.6/src/executor/current_thread/mod.rs:688
31: 0x10d2b47c0 - tokio::executor::current_thread::CurrentRunner::set_spawn::hb8bf56702d16822e
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.1.6/src/executor/current_thread/mod.rs:720
32: 0x10d2b6223 - <tokio::executor::current_thread::Borrow<'a, U>>::enter::{{closure}}::h0ba9110a83d0962b
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.1.6/src/executor/current_thread/mod.rs:687
33: 0x10d3720ab - <std::thread::local::LocalKey<T>>::try_with::hbdc69697c1f7c696
at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:379
34: 0x10d36f07a - <std::thread::local::LocalKey<T>>::with::h8e05ead11fc254eb
at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:293
35: 0x10d2b5fe1 - <tokio::executor::current_thread::Borrow<'a, U>>::enter::ha931faaf9ac76b8f
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.1.6/src/executor/current_thread/mod.rs:686
36: 0x10d2b72c9 - <tokio::executor::current_thread::Entered<'a, P>>::block_on::hdb6f0570032eacbf
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.1.6/src/executor/current_thread/mod.rs:463
37: 0x10d30ba02 - tokio_core::reactor::Core::run::{{closure}}::{{closure}}::{{closure}}::h056da405e7cde42b
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.16/src/reactor/mod.rs:251
38: 0x10d2900fd - tokio_executor::global::with_default::{{closure}}::h223a6823ee440a67
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-executor-0.1.2/src/global.rs:176
39: 0x10d372814 - <std::thread::local::LocalKey<T>>::try_with::hdc6d08b07cda0111
at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:379
40: 0x10d36efb2 - <std::thread::local::LocalKey<T>>::with::h64380b2058263a79
at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:293
41: 0x10d28fd5c - tokio_executor::global::with_default::hf0d7c2321a2f6d2e
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-executor-0.1.2/src/global.rs:150
42: 0x10d30b943 - tokio_core::reactor::Core::run::{{closure}}::{{closure}}::he223a226870ecf21
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.16/src/reactor/mod.rs:250
43: 0x10d3a31bf - tokio_reactor::with_default::{{closure}}::h46d792e53668b4ff
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-reactor-0.1.1/src/lib.rs:207
44: 0x10d371a3e - <std::thread::local::LocalKey<T>>::try_with::ha220c9b1b7208104
at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:379
45: 0x10d36f7ac - <std::thread::local::LocalKey<T>>::with::hf35d70e3a8e5a58e
at /Users/travis/build/rust-lang/rust/src/libstd/thread/local.rs:293
46: 0x10d3a2fbd - tokio_reactor::with_default::had214716788458cd
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-reactor-0.1.1/src/lib.rs:199
47: 0x10d30b461 - tokio_core::reactor::Core::run::{{closure}}::h49e11aabcd17ed65
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.16/src/reactor/mod.rs:249
48: 0x10d2d8e0c - <scoped_tls::ScopedKey<T>>::set::h9d36f3149bce1902
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/scoped-tls-0.1.0/src/lib.rs:135
49: 0x10d30b1ad - tokio_core::reactor::Core::run::hdb6f021fb1bb983c
at /Users/mh/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-core-0.1.16/src/reactor/mod.rs:248
50: 0x10d330a77 - spotty::main::h7fde15a2bf918426
at src/main.rs:474
51: 0x10e19e3dc - panic_unwind::dwarf::eh::read_encoded_pointer::hb58e97d57b98c61e
at src/libpanic_unwind/lib.rs:99
52: 0x10e191dc8 - <std::rand::reader::ReaderRng<R> as rand::Rng>::fill_bytes::hae12a5e967a5c965
at src/libstd/panicking.rs:459
at src/libstd/panic.rs:361
at src/libstd/rt.rs:59
53: 0x10d331444 - spotty::main::{{closure}}::h7c86a45143210067
DEBUG:librespot_connect::spirc: drop Spirc[0]
DEBUG:librespot_playback::player: Shutting down player thread ...
DEBUG:librespot_playback::player: drop Player[0]
DEBUG:librespot_core::session: drop Session[0]
DEBUG:librespot_core::mercury: drop MercuryManager
DEBUG:librespot_core::session: drop Dispatch
The discussion about "cannot recursively call into Core": https://github.com/tokio-rs/tokio-core/issues/319
mherger:
So… I’m trying to get rid of this. I understand I should pass the handle from main to the event handler, which in turn should return a future(?). But that’s where I’m stuck. Once I have the hyper::Request
, what would I need to do with it in order to have it processed?
Once you have a Handle to the running loop, you can spawn()
the request - that’ll run the request on the loop.
Would I do so inside the event handler? And what exactly would I spawn()? I can't client.request(req).spawn()
: "no method named spawn
found for type hyper::client::FutureResponse
in the current scope"
You need access to the Handle
, which represents a handle to the Core
that’s already running. Can you thread that through to your code?
Then you’d do:
let h: Handle = ...;
h.spawn(request);
Note that request
will need to be a Future<Item = (), Error = ()> + 'static
; practically, that means any error and result handling is contained within that future chain - it’s essentially a standalone task that runs in the loop, to completion, and doesn’t return an error or a value to anyone.
Here's roughly where I fail:
let client = Client::new(&handle);
let json = format!(r#"{{"id": 1,"method":"slim.request","params":["{}",{}]}}"#, player_mac, command);
let uri = Uri::from_str(base_url).unwrap();
let mut req = Request::new(Method::Post, uri);
req.headers_mut().set(ContentType::json());
req.headers_mut().set(ContentLength(json.len() as u64));
req.set_body(json);
let post = client.request(req);
handle.spawn(post);
But it's those last two lines which are causing me a headache... And I guess it's related to your very last comment "Note that request will need to be a Future<Item = (), Error = ()> + 'static;
". What am I missing?
tafia
May 18, 2018, 8:21am
7
You probably want to chain your future and manage the Response
/ error.
let post = client.request(req).and_then(|_res| {
/* work with the response here */
}).map_err(|_err| {
// and probably map your error as well
});
1 Like
It's what @tafia said. Based on your github code, you seem to not care about the result or the error, so that would just be:
let post = client.request(req).map(|_| ()).map_err(|_| ());
handle.spawn(post);
(You probably want to at least log the error, however).
Wow... I could have bet I had tried the .and_then()
version - but probably never read the resulting error message to the end. I was missing the use futures::Future
... added this, and it worked immediately. Thank you very much, guys!
A minor point is that and_then
is for when you want the closure given to it to return a future itself; if you just want to change the underlying future's result with synchronous code, use map()
.