These are chat archives for Alxandr/SpotiFire

7th
Feb 2015
Moritz Gunz
@NeoLegends
Feb 07 2015 13:15
yo
Aleksander Heintz
@Alxandr
Feb 07 2015 13:21
Yo
I think I had the same deadlock problem once btw
No clue what caused it though
Moritz Gunz
@NeoLegends
Feb 07 2015 13:23
The reason why I tried changing SetResult to TrySetResult was that I experience InvalidOperationExceptions when using SpotiFire in my own application
From time to time
Today it does not work at all
Sometimes it does
Aleksander Heintz
@Alxandr
Feb 07 2015 13:23
And you're sure it's caused by the SetResult call?
Moritz Gunz
@NeoLegends
Feb 07 2015 13:23
Pretty much
I tried using the one from NuGet
1.48
Then my customv ersion with TrySetResult
Aleksander Heintz
@Alxandr
Feb 07 2015 13:24
Cause as far as I know, it should be completely locked
Moritz Gunz
@NeoLegends
Feb 07 2015 13:24
-> Deadlock
Ah
Yeah, StackTrace reveals that SetResult causes the exception
Do you know whether visual studio supports debugging two different solutions at the same time?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:25
Yeah it does
Moritz Gunz
@NeoLegends
Feb 07 2015 13:25
Cause I'd like to debug SpotiFire as well while debugging Festify
Aleksander Heintz
@Alxandr
Feb 07 2015 13:25
Debugger doesn't care about solutions
Only projects
Moritz Gunz
@NeoLegends
Feb 07 2015 13:26
Okay
hmm
It works now
^^
Aleksander Heintz
@Alxandr
Feb 07 2015 13:26
Ok, so first of all, this should be Task::Run instead of Factory->StartNew: https://github.com/Alxandr/SpotiFire/blob/master/SpotiFire.LibSpotify/Session.cpp#L287
Where is the SetResult now again?
Moritz Gunz
@NeoLegends
Feb 07 2015 13:27
Ctrl + F
In my case, it happens inside the callback to logged_in
Aleksander Heintz
@Alxandr
Feb 07 2015 13:27
It's the login one?
Moritz Gunz
@NeoLegends
Feb 07 2015 13:27
yeah, this one
If I change that line to TrySetResult it does not want to load / play tracks
It logs in
But metadata is not available
Well, for your reference, this is what I'm working on
Aleksander Heintz
@Alxandr
Feb 07 2015 13:28
So, if you use TrySetResult, it prints the logged_in message, but stuff doesn't work?
Moritz Gunz
@NeoLegends
Feb 07 2015 13:28
I gotta check on that logging call, wait
This is what I'm currently working on
Party app for spotify
Kind of like Spartify
But better.
Aleksander Heintz
@Alxandr
Feb 07 2015 13:29
Looks good
Moritz Gunz
@NeoLegends
Feb 07 2015 13:29
festify.rocks
meh, not a single damn application supports the new top level domains
:D
Aleksander Heintz
@Alxandr
Feb 07 2015 13:30
Lol
Moritz Gunz
@NeoLegends
Feb 07 2015 13:30
If I use the custom version of SpotiFire, it cannot load the metadata
Aleksander Heintz
@Alxandr
Feb 07 2015 13:30
Anyways, I gave you collaborator on the repo
Moritz Gunz
@NeoLegends
Feb 07 2015 13:30
Yeah, I saw :)
Aleksander Heintz
@Alxandr
Feb 07 2015 13:30
Need to figure out how to allow you to push to nuget though
Moritz Gunz
@NeoLegends
Feb 07 2015 13:31
So, whats the direction you want to get SpotiFire into?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:31
Well, I have 2 end goal plans
Moritz Gunz
@NeoLegends
Feb 07 2015 13:31
I think you can add me as owner or collaborator or something
Aleksander Heintz
@Alxandr
Feb 07 2015 13:31
One of which is xplat
So, eventually, I'll have to rewrite it back to C#
Hopefully, I've learned enough about libspotify now that it shouldn't be too much of a problem
Moritz Gunz
@NeoLegends
Feb 07 2015 13:32
You started it in C++ because of the native haeder?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:32
I initially rewrote it into C++ because of some P/Invoke problems
And the native header solved that
Moritz Gunz
@NeoLegends
Feb 07 2015 13:32
Ahh
Well, I still have the DotNetify repo
Its a start
Aleksander Heintz
@Alxandr
Feb 07 2015 13:33
Spesifically, I could not get the information about whether or not a track was starred
(this was way back when starring was still a thing ^^)
Moritz Gunz
@NeoLegends
Feb 07 2015 13:33
:D
Aleksander Heintz
@Alxandr
Feb 07 2015 13:33
The bool method returned a pointer ^^
Moritz Gunz
@NeoLegends
Feb 07 2015 13:33
oh
Aleksander Heintz
@Alxandr
Feb 07 2015 13:33
And I was like, woot?
Moritz Gunz
@NeoLegends
Feb 07 2015 13:33
And it was not a 0 / 1-pointer?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:33
No
Moritz Gunz
@NeoLegends
Feb 07 2015 13:33
lol
Aleksander Heintz
@Alxandr
Feb 07 2015 13:33
It was like a huge memory address
Moritz Gunz
@NeoLegends
Feb 07 2015 13:33
lol
Perhaps you had to dereference it? ^^
Aleksander Heintz
@Alxandr
Feb 07 2015 13:34
Tried that
Moritz Gunz
@NeoLegends
Feb 07 2015 13:34
No bool there?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:34
Got more random data
Moritz Gunz
@NeoLegends
Feb 07 2015 13:34
;)
yay
Aleksander Heintz
@Alxandr
Feb 07 2015 13:34
Probably just something wrong in my [DllImport]
So it ran the wrong native method
Moritz Gunz
@NeoLegends
Feb 07 2015 13:34
Is there a M/C++ -> C# translator?
perhaps
Aleksander Heintz
@Alxandr
Feb 07 2015 13:34
Well, sort off
What one can do is compile the C++ with /clr:pure
Moritz Gunz
@NeoLegends
Feb 07 2015 13:35
Does it generate intermediate C# code?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:35
Which will gen a pure IL assembly
Moritz Gunz
@NeoLegends
Feb 07 2015 13:35
Decompile -> C#
Got it.
Aleksander Heintz
@Alxandr
Feb 07 2015 13:35
And then it can be decompiled
Moritz Gunz
@NeoLegends
Feb 07 2015 13:35
:ÖD
Aleksander Heintz
@Alxandr
Feb 07 2015 13:35
Yeah, so we'd get the correct [DllImport] at least
Moritz Gunz
@NeoLegends
Feb 07 2015 13:35
You know what we may do?
Split that stuff into two assemblies
One in M/C++
Which exposes just a single class
NativeMethods or something
Aleksander Heintz
@Alxandr
Feb 07 2015 13:36
Still won't be xplat
Moritz Gunz
@NeoLegends
Feb 07 2015 13:36
And the rest goes into a separate assemblie
Why?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:36
Cause only windows can handle M/C++
Moritz Gunz
@NeoLegends
Feb 07 2015 13:36
If we compile it with /clr:pure it should?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:36
Right
Moritz Gunz
@NeoLegends
Feb 07 2015 13:36
So whats the problem?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:36
But then, there's no real point in the M/C++ one
Moritz Gunz
@NeoLegends
Feb 07 2015 13:36
Well, no building on Linux
Yes, proper marshalling
Aleksander Heintz
@Alxandr
Feb 07 2015 13:37
Yeah, but that's a one time deal
Moritz Gunz
@NeoLegends
Feb 07 2015 13:37
Yeah
Aleksander Heintz
@Alxandr
Feb 07 2015 13:37
So just getting the correct [DllImport] one time, and it could all be in C#
Would probably also use the vnext project system to get free nuget packages
Moritz Gunz
@NeoLegends
Feb 07 2015 13:39
Whats that?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:39
It's the technology used to build Asp .NET 5 projects
But it can be used for stuff that's not web
Moritz Gunz
@NeoLegends
Feb 07 2015 13:39
Roslyn?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:39
Well, yeah, that too
Moritz Gunz
@NeoLegends
Feb 07 2015 13:40
We could wait until VS 2015 is released
Aleksander Heintz
@Alxandr
Feb 07 2015 13:40
But the main point is that there's no .csproj
And that it's not tied to visual studio
And it builds easily on all platforms
Moritz Gunz
@NeoLegends
Feb 07 2015 13:40
Sounds good
What about Contracts?
Code Contracts?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:41
Doesn't (at least yet) support them
I don't think they plan to either
Moritz Gunz
@NeoLegends
Feb 07 2015 13:41
:/
Aleksander Heintz
@Alxandr
Feb 07 2015 13:42
Also, I'd like to add a new (optional) level of abstraction on top of the libspotify API
Moritz Gunz
@NeoLegends
Feb 07 2015 13:42
I'd be "careful" with that
Aleksander Heintz
@Alxandr
Feb 07 2015 13:42
Because, currently, when you get TrackEnded event, it doesn't really mean that the track has ended
It just means that all the data has been delivered
I started work a while back in a branch named feature-buffer
Moritz Gunz
@NeoLegends
Feb 07 2015 13:43
Festify, at least, needs that low-level API. We plan on adding multiple music sources in the future. Thus we need an API every source can provide (PCM streams).
Aleksander Heintz
@Alxandr
Feb 07 2015 13:44
Yeah, but it would still be the same low level
You'd get bytes out
Moritz Gunz
@NeoLegends
Feb 07 2015 13:44
how about crossfades and stuff?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:44
Well, that's the thing. I'd like the ability to support that in SpotiFire. With (obviously) optional usage.
Moritz Gunz
@NeoLegends
Feb 07 2015 13:45
Okay
Aleksander Heintz
@Alxandr
Feb 07 2015 13:46
What I'm thinking is to remove the event DataReceived (or whatever it's called), and rather have an interface you can provide to the Session, an IBuffer
Moritz Gunz
@NeoLegends
Feb 07 2015 13:46
If you'd like to port the project back to C#, we could use DotNetify (my own libspotify wrapper before I discovered yours). It's 100% C#.
As a "kickstart"
Ahh
Aleksander Heintz
@Alxandr
Feb 07 2015 13:47
If you go back in history of SpotiFire you'll also see it's in C#
Moritz Gunz
@NeoLegends
Feb 07 2015 13:47
Wouldn't a Stream be a better choice in that case?
Aleksander Heintz
@Alxandr
Feb 07 2015 13:47
Way back
No
Moritz Gunz
@NeoLegends
Feb 07 2015 13:47
Damn, gotta go
I'll be back in two hours or something
Aleksander Heintz
@Alxandr
Feb 07 2015 13:47
You don't generally want it to be a stream
Cause, you need to provide the libspotify methods
Moritz Gunz
@NeoLegends
Feb 07 2015 15:34
Re
Had to pick my sister up from rowing
The only libspotify method that needs to be supported besides music delivery would be AudioBufferStats, right?
The stream could handle that automatically, I think.
Make it work like abuffer / memorystream, and subtract the read bytes from the stored bytes.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:37
Hmm
Moritz Gunz
@NeoLegends
Feb 07 2015 15:37
respectively their count
This way, SpotiFire could expose a Stream
Aleksander Heintz
@Alxandr
Feb 07 2015 15:37
Yeah
Moritz Gunz
@NeoLegends
Feb 07 2015 15:38
We'll have to see
Aleksander Heintz
@Alxandr
Feb 07 2015 15:38
Problem is though
A stream gives the indication that you can just read
Moritz Gunz
@NeoLegends
Feb 07 2015 15:38
Having a Stream would make libspotify compatible with almost any API
Aleksander Heintz
@Alxandr
Feb 07 2015 15:38
Not sure it's the right datatype
Moritz Gunz
@NeoLegends
Feb 07 2015 15:38
But you can just read
Aleksander Heintz
@Alxandr
Feb 07 2015 15:38
No
Cause, the data might not be there yet
Moritz Gunz
@NeoLegends
Feb 07 2015 15:39
Yeah, but thats exactly what streams are made for, I think
File-Downloads are the same thing
Aleksander Heintz
@Alxandr
Feb 07 2015 15:39
So then the question is, do you block? Or do you return 0s
Moritz Gunz
@NeoLegends
Feb 07 2015 15:39
The data is not fully there, yet you can read whats there
Return 0, as one is supposed to
Wait, I'll check MSDN
Aleksander Heintz
@Alxandr
Feb 07 2015 15:39
Yeah, but streams that you read and get length = 0 means the stream is closed
Moritz Gunz
@NeoLegends
Feb 07 2015 15:39
Oh
Okay
Didn't know that
Well, makes sense.
Then you're right. Stream is not the right data type.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:40
Normally when I read streams I do
while(read > 0) {
  read = stream.Read(buffer, 0, buffer.Length);
  // do stuff with data
}
Moritz Gunz
@NeoLegends
Feb 07 2015 15:41
I usually don't read streams by myself. I usually use a StreamReader or something that does all that for me :D
Aleksander Heintz
@Alxandr
Feb 07 2015 15:41
Yeah, and that get's even worse
Moritz Gunz
@NeoLegends
Feb 07 2015 15:41
But if I think about it, it makes sense. One can't always throw an exception if the stream has ended. That would hurt performance.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:42
But it hasn't ended
It never ends, right?
Moritz Gunz
@NeoLegends
Feb 07 2015 15:42
Spotify?
Aleksander Heintz
@Alxandr
Feb 07 2015 15:42
There is always more music data coming
Moritz Gunz
@NeoLegends
Feb 07 2015 15:42
As long as track_ended didn't fire music data is coming
Aleksander Heintz
@Alxandr
Feb 07 2015 15:42
No, but the buffer isn't per-track
Moritz Gunz
@NeoLegends
Feb 07 2015 15:42
It is
At least, usually
Aleksander Heintz
@Alxandr
Feb 07 2015 15:43
Hmm
Moritz Gunz
@NeoLegends
Feb 07 2015 15:43
I have not tried using the same buffer for two tracks, but I always flush my buffers when a track has ended.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:43
Need to think about this
Moritz Gunz
@NeoLegends
Feb 07 2015 15:43
To ensure everything is gone and reset
And if track_ended has fired, no more music data will be on the way.
Because then you do have all you need for that specific track
Aleksander Heintz
@Alxandr
Feb 07 2015 15:44
Yeah, but, if it's exposed as session.Stream
Moritz Gunz
@NeoLegends
Feb 07 2015 15:44
Yeah, we can't do that
Aleksander Heintz
@Alxandr
Feb 07 2015 15:44
Does that mean you have to re-grab it for every track?
Moritz Gunz
@NeoLegends
Feb 07 2015 15:44
Well
Just now I had that thought as well
We might implement something like
Stream PlayerPlay(Track track) { ... }
Aleksander Heintz
@Alxandr
Feb 07 2015 15:45
Yeah, but you can't really do that
Moritz Gunz
@NeoLegends
Feb 07 2015 15:45
Because we'd need to ensure theres always data available
Which we can't without blocking.
In theory
We could block.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:46
But problem with Stream PlayerPlay is this:
If I go PlayerPlay(track1)
And grab the stream
Then immediately do PlayerPlay(track2)
You have a problem
Moritz Gunz
@NeoLegends
Feb 07 2015 15:46
We'd need to implement some sort of dispose-method that handles those cases.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:47
Yeah.
We could just close it
Moritz Gunz
@NeoLegends
Feb 07 2015 15:47
A mechanism that keeps weak references to all the streams it has given out, and that closes those if a new track is being played.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:47
No, you only need the current
No point in keeping all
Moritz Gunz
@NeoLegends
Feb 07 2015 15:47
And I'd like to expose the subtype of the stream
Aleksander Heintz
@Alxandr
Feb 07 2015 15:48
Yeah
Moritz Gunz
@NeoLegends
Feb 07 2015 15:48
Oh, yeah.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:48
Agreed
Moritz Gunz
@NeoLegends
Feb 07 2015 15:48
Because we then can expose an event
Aleksander Heintz
@Alxandr
Feb 07 2015 15:48
MusicStream or something
Moritz Gunz
@NeoLegends
Feb 07 2015 15:48
Yeah
Because with streams, you'd have to loop for new data
At least with NetworkStraem
Idea
We could take a look at how NetworkStream is implemented
Aleksander Heintz
@Alxandr
Feb 07 2015 15:48
It's blocking
Moritz Gunz
@NeoLegends
Feb 07 2015 15:48
Because NetworkStream should be similar to what we do
Well, we've got our answer then. :D
Aleksander Heintz
@Alxandr
Feb 07 2015 15:49
No
We can't block
Blocking is really bad in music applications
It causes stutter
Moritz Gunz
@NeoLegends
Feb 07 2015 15:49
You know what? We won't really need to care about blocking.
Only when we start playback.
Only about the initial block when libspotify loads the track
Because after it has fetched the PCM data, it will ensure there is enough data inside the stream.
Through AudioBufferStats
Right?
Actually, there also is a better way than closing the old stream.
Aleksander Heintz
@Alxandr
Feb 07 2015 15:51
Which is?
Moritz Gunz
@NeoLegends
Feb 07 2015 15:51
We could implement some sort of "router" that routes the PCM data to the newest stream
This way, the old ones stay alive and can be used until all their PCM data has been consumed
If we disposed all the old streams, we couldn't crossfade.
Since it depends on data already inside the buffers.
Moritz Gunz
@NeoLegends
Feb 07 2015 15:53
Yeah, I'm using that in Festify
Aleksander Heintz
@Alxandr
Feb 07 2015 15:53
I didn't say dispose
I said close
Moritz Gunz
@NeoLegends
Feb 07 2015 15:53
Doesn't that do the same in case of streams?
Aleksander Heintz
@Alxandr
Feb 07 2015 15:53
No, I just mean that we signal that the stream has ended. So that when you read to a certain point, it returns 0 length
Moritz Gunz
@NeoLegends
Feb 07 2015 15:53
Ahh
yeah
Aleksander Heintz
@Alxandr
Feb 07 2015 15:53
Though
We can't use stream
Moritz Gunz
@NeoLegends
Feb 07 2015 15:53
I think a simple MemoryStream as the underlying implementation would suffice
Aleksander Heintz
@Alxandr
Feb 07 2015 15:54
Cause we need more data
Or rather, we could subclass it
But I think it's better to use something else
We need info such as sample format
Moritz Gunz
@NeoLegends
Feb 07 2015 15:54
What additional data to we need?
Aleksander Heintz
@Alxandr
Feb 07 2015 15:54
bits/sec
Moritz Gunz
@NeoLegends
Feb 07 2015 15:54
hmm
Indeed
I'm not sure. I really like the idea of representing the music data as a stream - which it essentially is - because it allows for simple interop between libspotify and a huge set of already existing libraries.
The format could be stored inside the subclass
Its difficult to decide
Aleksander Heintz
@Alxandr
Feb 07 2015 15:56
I'd rather go with a simple stream wrapper (we can provide)
If you really need a stream
Moritz Gunz
@NeoLegends
Feb 07 2015 15:56
So our custom implementation at the base, and a stream on top?
Aleksander Heintz
@Alxandr
Feb 07 2015 15:57
Yeah. And our custom implementation will be fairly similar to a stream, so the wrapper will be really thin and easy to make
Moritz Gunz
@NeoLegends
Feb 07 2015 15:57
Yes.
Sounds good.
So, how do we want the IBuffer interface to look like?
Or rather, do we want to read from IBuffer or do we want to receive data inside it?
Aleksander Heintz
@Alxandr
Feb 07 2015 15:59
Read
Moritz Gunz
@NeoLegends
Feb 07 2015 15:59
So similar to Stream.Read?
Moritz Gunz
@NeoLegends
Feb 07 2015 16:00
Ah, okay.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:00
Something like that
Moritz Gunz
@NeoLegends
Feb 07 2015 16:01
We could also pull NAudio as a dependency in, and expose a WaveProvider directly
We'd add 500kb to the deployment size, though.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:01
Yeah, I don't want to do that
Moritz Gunz
@NeoLegends
Feb 07 2015 16:01
Perhaps as a separate assembly that can be deployed alongside SpotiFire.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:01
Yeah. That'd be easy.
Moritz Gunz
@NeoLegends
Feb 07 2015 16:02
Couple of extension methods and we're good to go.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:02
Cause we basically use the same format, so converting would also be a really simple wrapper
And an extension method probably, yeah
Maybe even an implicit operator
Moritz Gunz
@NeoLegends
Feb 07 2015 16:02
yeah
PInvoke is xplat, right?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:03
Yes
Moritz Gunz
@NeoLegends
Feb 07 2015 16:03
Mono implements it?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:03
Yeah
The original SpotiFire only worked on linux xD
Moritz Gunz
@NeoLegends
Feb 07 2015 16:03
^^
Aleksander Heintz
@Alxandr
Feb 07 2015 16:03
(libspotify didn't do windows back then)
Moritz Gunz
@NeoLegends
Feb 07 2015 16:03
Are you working on linux?
lol
Aleksander Heintz
@Alxandr
Feb 07 2015 16:03
No, I was for a short while
Moritz Gunz
@NeoLegends
Feb 07 2015 16:03
Ah
I really wonder why they do not release a 64 bit version for windows
Every other friggin platform gets 64 bit support
Except for windows
Aleksander Heintz
@Alxandr
Feb 07 2015 16:04
Yeah
Moritz Gunz
@NeoLegends
Feb 07 2015 16:04
Well, my attitude towars 64 bit is: if you can, use it. Even if you don't need the additional RAM.
64 bits are the future, we should move to it.
Not stay on 32, because it "still runs".
Have you worked with NAudio already?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:07
Yeah
The SpotiFire demos use NAudio
Moritz Gunz
@NeoLegends
Feb 07 2015 16:07
What is the most stable audio out in your opinion?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:08
Not really much of a difference between them
Moritz Gunz
@NeoLegends
Feb 07 2015 16:08
Ah, I must admit I unloaded those because I didn't need them and I didn't want visual studio to slow down :'D
Okay
WaveOutEvent did a pretty good job, but it stutters if I open chrome
Well, my PC is not the beastiest one anymore, but still I wondered.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:14
In general, it got a lot better during update to libspotify ~0.9 or something like that
Moritz Gunz
@NeoLegends
Feb 07 2015 16:15
You said you want to replace Task.Factory by Task.Run
I think we shouldn't do that
Task.Factory accepts a TaskCreationOptions parameter, which we could set to LongRunning
As a hint for the Task Scheduler
Moritz Gunz
@NeoLegends
Feb 07 2015 16:17
Ah
It says it'll adjust automatically
Okay, won't need that.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:17
The main problem with StartNew is that it only awaits the first "task"
Not any subsequent ones
Moritz Gunz
@NeoLegends
Feb 07 2015 16:17
?
So any continuations with ContinueWith won't be awaited?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:19
await Task.Run(async () => {
    Console.WriteLine("blah1");
    await Task.Delay(1000);
    Console.WriteLine("blah2");
});
Console.WriteLine("done");
If you do the same with startnew, done will be printed before "blah2"
Moritz Gunz
@NeoLegends
Feb 07 2015 16:19
Will write Blah, done, and blah2, if it was written with Task.Factory, right?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:19
But with run, it's blah1, blah2 and done
Moritz Gunz
@NeoLegends
Feb 07 2015 16:19
Ah, okay
DIdn't know that. :)
Moritz Gunz
@NeoLegends
Feb 07 2015 16:27
Are there lambdas in M/C++?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:29
Ish
But in general, no
Moritz Gunz
@NeoLegends
Feb 07 2015 16:29
Okay
There you go
It happened again.
I'm not sure, but it seems to call that thing twice.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:38
And the exception is?
Moritz Gunz
@NeoLegends
Feb 07 2015 16:40
InvalidOperationException
Aleksander Heintz
@Alxandr
Feb 07 2015 16:40
Hmm
Moritz Gunz
@NeoLegends
Feb 07 2015 16:41
"Es wurde versucht, eine Aufgabe in einen finalen Zustand zu versetzen, als sie bereits abgeschlossen war."
I'm not sure whether you can understand it
Aleksander Heintz
@Alxandr
Feb 07 2015 16:41
Nope
Moritz Gunz
@NeoLegends
Feb 07 2015 16:41
Its the exception being thrown if you try to set the result of a TCS twice.
"It was tried to set the result of a task even though it was already finished." or something
Aleksander Heintz
@Alxandr
Feb 07 2015 16:43
Check the log
Moritz Gunz
@NeoLegends
Feb 07 2015 16:45
Jep
logged_in appears twice
Aleksander Heintz
@Alxandr
Feb 07 2015 16:46
Does "login" do too?
(or is that even logged)
Moritz Gunz
@NeoLegends
Feb 07 2015 16:46
Only once
2015-02-07 17:44:53.8527 | TRACE | SpotiFire.Session | Create | 
2015-02-07 17:44:53.8527 | TRACE | SpotiFire.Session | Ctor | 
2015-02-07 17:44:53.8567 | TRACE | SpotiFire.Session | set_PreferredBitrate | 
2015-02-07 17:44:53.8567 | TRACE | SpotiFire.Session | set_PreferredOfflineBitrate | 
2015-02-07 17:44:53.8567 | TRACE | SpotiFire.Session | set_CacheSize | 
2015-02-07 17:44:53.8567 | TRACE | SpotiFire.Session | set_VolumeNormalization | 
2015-02-07 17:44:53.9487 | TRACE | Festify.Desktop.ViewModels.MainViewModel | Creating a new MainViewModel. | 
2015-02-07 17:44:53.9587 | TRACE | Festify.Desktop.Model.MainModel | Creating a new MainModel. | 
2015-02-07 17:44:53.9587 | TRACE | Festify.Desktop.Model.LoginModel | Creating a new LoginModel. | 
2015-02-07 17:44:53.9717 | TRACE | Festify.Desktop.ViewModels.LoginViewModel | Creating a new LoginViewModel. | 
2015-02-07 17:44:53.9717 | TRACE | SpotiFire.Session | Login | 
2015-02-07 17:44:53.9847 | TRACE | SpotiFire.Session | logged_in | 
2015-02-07 17:44:53.9847 | TRACE | SpotiFire.Session | log_message | 
2015-02-07 17:44:53.9847 | TRACE | SpotiFire.Session | credentials_blob_updated | 
2015-02-07 17:44:53.9987 | TRACE | SpotiFire.Session | log_message | 
2015-02-07 17:44:53.9987 | TRACE | SpotiFire.Session | connectionstate_updated | 
2015-02-07 17:44:53.9987 | TRACE | SpotiFire.Session | metadata_updated | 
2015-02-07 17:44:53.9987 | TRACE | SpotiFire.Session | get_ConnectionState | 
2015-02-07 17:44:54.0127 | TRACE | SpotiFire.Session | log_message | 
2015-02-07 17:44:54.0127 | TRACE | Festify.Desktop.ViewModels.StartViewModel | Creating a new StartViewModel. | 
2015-02-07 17:44:54.0447 | TRACE | SpotiFire.Session | log_message | 
2015-02-07 17:44:54.2337 | TRACE | SpotiFire.Session | log_message | 
2015-02-07 17:44:54.2337 | TRACE | SpotiFire.Session | logged_in | 
2015-02-07 17:44:54.2337 | TRACE | SpotiFire.Session | connectionstate_updated | 
2015-02-07 17:44:54.2337 | TRACE | SpotiFire.Session | get_ConnectionState |
Aleksander Heintz
@Alxandr
Feb 07 2015 16:46
Interesting
Moritz Gunz
@NeoLegends
Feb 07 2015 16:46
Indeed
Aleksander Heintz
@Alxandr
Feb 07 2015 16:47
probably has something to do withe connectionstate_updated that occurs just after
Moritz Gunz
@NeoLegends
Feb 07 2015 16:47
Strangely enough, this happens only when its run outside of the debugger
At least today
Aleksander Heintz
@Alxandr
Feb 07 2015 16:47
Yeah, typical for timing issues
Moritz Gunz
@NeoLegends
Feb 07 2015 16:47
A week ago, running Festify in the debugger crashed it, while it worked without it
Perhaps, yeah.
I'm gonna see if I can debug it
Aleksander Heintz
@Alxandr
Feb 07 2015 16:48
No, but it's probably not an actual error
Just clear out the tcs after it's set
Moritz Gunz
@NeoLegends
Feb 07 2015 16:48
haha
I had the same idea just now :D
I'll set it to null.
Ahh
Help pls
Aleksander Heintz
@Alxandr
Feb 07 2015 16:50
?
Moritz Gunz
@NeoLegends
Feb 07 2015 16:50
How do I pass an item by reference in M/C++?
Its ref in C#
ByRef in VS
But in M/C++?
Aleksander Heintz
@Alxandr
Feb 07 2015 16:51
You just pass it
Moritz Gunz
@NeoLegends
Feb 07 2015 16:51
I'm trying to use Interlocked.Exchange
Aleksander Heintz
@Alxandr
Feb 07 2015 16:51
Yeah
I use that multiple places IIRC
Just do Interlocked::Exchange(variable, neValue);
Moritz Gunz
@NeoLegends
Feb 07 2015 16:52
void Session::logged_in(Error error) {
    logger->Trace("logged_in");
    TaskCompletionSource<SpotiFire::Error> ^tcs = Interlocked::Exchange<TaskCompletionSource<SpotiFire::Error>>(_login, nullptr);
    if(tcs) {
        tcs->SetResult(error);
    }
}
Theres some error left
wow
Sorry, not anymore
VS was a little slower with analyzing than me
Okay, everything alright. :)
I'll do the same for logout
wait
Now it says it doesn't work.
Aleksander Heintz
@Alxandr
Feb 07 2015 16:54
?
Moritz Gunz
@NeoLegends
Feb 07 2015 16:55
It says the argument list of Interlocked.Exchange does not match
with the given parameters
Aleksander Heintz
@Alxandr
Feb 07 2015 17:09
Hmm
Not sure
Aleksander Heintz
@Alxandr
Feb 07 2015 18:06
So, I did a quick test of how stuff would look in C#
Will push later though