├── LICENSE
├── README.md
├── example
├── example_gl_video.go
└── example_video.go
└── mpv
├── consts.go
├── error.go
├── mpv.go
├── mpvgl.go
├── node.go
├── node_test.go
└── procaddr.go
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GO-MPV
2 |
3 | Golang bindings for libmpv
4 |
5 | ## Node not implemented
6 |
7 |
8 | # Examples
9 | - https://github.com/aykevl93/plaincast
10 | - https://github.com/dz0ny/champ#usage-spinwheel
11 | - https://github.com/YouROK/SRadio
12 |
--------------------------------------------------------------------------------
/example/example_gl_video.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "runtime"
6 |
7 | "github.com/go-gl/gl/v3.2-core/gl"
8 | "github.com/go-gl/glfw/v3.1/glfw"
9 | "github.com/yourok/go-mpv/mpv"
10 | )
11 |
12 | func init() {
13 | runtime.LockOSThread()
14 | }
15 |
16 | func main() {
17 | //Init gl
18 | err := glfw.Init()
19 | if err != nil {
20 | log.Println(err)
21 | panic(err)
22 | }
23 | defer glfw.Terminate()
24 |
25 | window, err := glfw.CreateWindow(640, 480, "Testing", nil, nil)
26 | if err != nil {
27 | panic(err)
28 | }
29 |
30 | window.MakeContextCurrent()
31 |
32 | if err := gl.Init(); err != nil {
33 | panic(err)
34 | }
35 |
36 | //init mpv
37 | m := mpv.Create()
38 | defer m.TerminateDestroy()
39 |
40 | m.SetOption("no-resume-playback", mpv.FORMAT_FLAG, true)
41 | m.SetOption("softvol", mpv.FORMAT_STRING, "yes")
42 | m.SetOption("volume", mpv.FORMAT_INT64, 20)
43 | m.SetOption("mute", mpv.FORMAT_FLAG, true)
44 | m.SetOptionString("hwdec", "auto")
45 |
46 | //cache
47 | m.SetOption("cache-default", mpv.FORMAT_INT64, 160)
48 | m.SetOption("cache-seek-min", mpv.FORMAT_INT64, 16)
49 |
50 | //GL
51 | m.SetOptionString("vo", "opengl-cb")
52 |
53 | err = m.Initialize()
54 | if err != nil {
55 | log.Println("Mpv init:", err.Error())
56 | return
57 | }
58 | //Set video file
59 | m.Command([]string{"loadfile", "http://techslides.com/demos/sample-videos/small.webm"})
60 |
61 | //Init mpv gl
62 | mgl := m.GetSubApiGL()
63 | if mgl == nil {
64 | return
65 | }
66 |
67 | mgl.InitGL()
68 | defer mgl.UninitGL()
69 |
70 | //Draw
71 | for !window.ShouldClose() {
72 | mgl.Draw(0, 640, 480)
73 | window.SwapBuffers()
74 | glfw.PollEvents()
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/example/example_video.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | // "time"
6 |
7 | "github.com/yourok/go-mpv/mpv"
8 | )
9 |
10 | func eventListener(m *mpv.Mpv) chan *mpv.Event {
11 | c := make(chan *mpv.Event)
12 | go func() {
13 | for {
14 | e := m.WaitEvent(1)
15 | c <- e
16 | }
17 | }()
18 | return c
19 | }
20 |
21 | func main() {
22 | m := mpv.Create()
23 | c := eventListener(m)
24 | log.Println("no-resume-playback", m.SetOption("no-resume-playback", mpv.FORMAT_FLAG, true))
25 | log.Println("volume", m.SetOption("volume", mpv.FORMAT_INT64, 20))
26 | log.Println("terminal", m.SetOptionString("terminal", "yes"))
27 | log.Println("softvol", m.SetOptionString("softvol", "yes"))
28 |
29 | // Disable video in three ways.
30 | //m.SetOption("no-video", mpv.FORMAT_FLAG, true)
31 | //m.SetOption("vo", mpv.FORMAT_STRING, "null")
32 | //m.SetOption("vid", mpv.FORMAT_STRING, "")
33 |
34 | //cache
35 | log.Println("cache-default", m.SetOption("cache-default", mpv.FORMAT_INT64, 160)) // 10 seconds
36 | log.Println("cache-seek-min", m.SetOption("cache-seek-min", mpv.FORMAT_INT64, 16)) // 1 second
37 |
38 | err := m.Initialize()
39 | if err != nil {
40 | log.Println("Mpv init:", err.Error())
41 | return
42 | }
43 | //Set video file
44 | log.Println("loadfile", m.Command([]string{"loadfile", "http://techslides.com/demos/sample-videos/small.webm"}))
45 |
46 | for {
47 | e := <-c
48 | log.Println(e)
49 | if e.Event_Id == mpv.EVENT_END_FILE {
50 | break
51 | }
52 |
53 | /*{
54 | pos, err := m.GetProperty("time-pos", mpv.FORMAT_DOUBLE)
55 | if err != nil {
56 | log.Println("time-pos", err)
57 | continue
58 | }
59 | vol, err := m.GetProperty("volume", mpv.FORMAT_DOUBLE)
60 | //log.Println(pos.(float64))
61 | if err != nil {
62 | log.Println("volume", err)
63 | continue
64 | }
65 | {
66 | position := pos.(float64)
67 | if position < 0 {
68 | position = 0
69 | }
70 | log.Println(time.Duration(position * float64(time.Second)))
71 | log.Println(vol)
72 | }
73 | }*/
74 |
75 | }
76 | m.TerminateDestroy()
77 | }
78 |
--------------------------------------------------------------------------------
/mpv/consts.go:
--------------------------------------------------------------------------------
1 | package mpv
2 |
3 | //#include
4 | import "C"
5 |
6 | //Errors mpv_error
7 | const (
8 | /**
9 | * No error happened (used to signal successful operation).
10 | * Keep in mind that many API functions returning error codes can also
11 | * return positive values, which also indicate success. API users can
12 | * hardcode the fact that ">= 0" means success.
13 | */
14 | ERROR_SUCCESS Error = C.MPV_ERROR_SUCCESS
15 | /**
16 | * The event ringbuffer is full. This means the client is choked, and can't
17 | * receive any events. This can happen when too many asynchronous requests
18 | * have been made, but not answered. Probably never happens in practice,
19 | * unless the mpv core is frozen for some reason, and the client keeps
20 | * making asynchronous requests. (Bugs in the client API implementation
21 | * could also trigger this, e.g. if events become "lost".)
22 | */
23 | ERROR_EVENT_QUEUE_FULL Error = C.MPV_ERROR_EVENT_QUEUE_FULL
24 | /**
25 | * Memory allocation failed.
26 | */
27 | ERROR_NOMEM Error = C.MPV_ERROR_NOMEM
28 | /**
29 | * The mpv core wasn't configured and initialized yet. See the notes in
30 | * mpv_create().
31 | */
32 | ERROR_UNINITIALIZED Error = C.MPV_ERROR_UNINITIALIZED
33 | /**
34 | * Generic catch-all error if a parameter is set to an invalid or
35 | * unsupported value. This is used if there is no better error code.
36 | */
37 | ERROR_INVALID_PARAMETER Error = C.MPV_ERROR_INVALID_PARAMETER
38 | /**
39 | * Trying to set an option that doesn't exist.
40 | */
41 | ERROR_OPTION_NOT_FOUND Error = C.MPV_ERROR_OPTION_NOT_FOUND
42 | /**
43 | * Trying to set an option using an unsupported MPV_FORMAT.
44 | */
45 | ERROR_OPTION_FORMAT Error = C.MPV_ERROR_OPTION_FORMAT
46 | /**
47 | * Setting the option failed. Typically this happens if the provided option
48 | * value could not be parsed.
49 | */
50 | ERROR_OPTION_ERROR Error = C.MPV_ERROR_OPTION_ERROR
51 | /**
52 | * The accessed property doesn't exist.
53 | */
54 | ERROR_PROPERTY_NOT_FOUND Error = C.MPV_ERROR_PROPERTY_NOT_FOUND
55 | /**
56 | * Trying to set or get a property using an unsupported MPV_FORMAT.
57 | */
58 | ERROR_PROPERTY_FORMAT Error = C.MPV_ERROR_PROPERTY_FORMAT
59 | /**
60 | * The property exists, but is not available. This usually happens when the
61 | * associated subsystem is not active, e.g. querying audio parameters while
62 | * audio is disabled.
63 | */
64 | ERROR_PROPERTY_UNAVAILABLE Error = C.MPV_ERROR_PROPERTY_UNAVAILABLE
65 | /**
66 | * Error setting or getting a property.
67 | */
68 | ERROR_PROPERTY_ERROR Error = C.MPV_ERROR_PROPERTY_ERROR
69 | /**
70 | * General error when running a command with mpv_command and similar.
71 | */
72 | ERROR_COMMAND Error = C.MPV_ERROR_COMMAND
73 | /**
74 | * Generic error on loading (used with mpv_event_end_file.error).
75 | */
76 | ERROR_LOADING_FAILED Error = C.MPV_ERROR_LOADING_FAILED
77 | /**
78 | * Initializing the audio output failed.
79 | */
80 | ERROR_AO_INIT_FAILED Error = C.MPV_ERROR_AO_INIT_FAILED
81 | /**
82 | * Initializing the video output failed.
83 | */
84 | ERROR_VO_INIT_FAILED Error = C.MPV_ERROR_VO_INIT_FAILED
85 | /**
86 | * There was no audio or video data to play. This also happens if the
87 | * file was recognized, but did not contain any audio or video streams,
88 | * or no streams were selected.
89 | */
90 | ERROR_NOTHING_TO_PLAY Error = C.MPV_ERROR_NOTHING_TO_PLAY
91 | /**
92 | * When trying to load the file, the file format could not be determined,
93 | * or the file was too broken to open it.
94 | */
95 | ERROR_UNKNOWN_FORMAT Error = C.MPV_ERROR_UNKNOWN_FORMAT
96 | /**
97 | * Generic error for signaling that certain system requirements are not
98 | * fulfilled.
99 | */
100 | ERROR_UNSUPPORTED Error = C.MPV_ERROR_UNSUPPORTED
101 | /**
102 | * The API function which was called is a stub only.
103 | */
104 | MPV_ERROR_NOT_IMPLEMENTED Error = C.MPV_ERROR_UNSUPPORTED
105 | )
106 |
107 | type Format int
108 |
109 | //Format mpv_format
110 | const (
111 | FORMAT_NONE Format = C.MPV_FORMAT_NONE
112 | /**
113 | * The basic type is char*. It returns the raw property string, like
114 | * using ${=property} in input.conf (see input.rst).
115 | *
116 | * NULL isn't an allowed value.
117 | *
118 | * Warning: although the encoding is usually UTF-8, this is not always the
119 | * case. File tags often store strings in some legacy codepage,
120 | * and even filenames don't necessarily have to be in UTF-8 (at
121 | * least on Linux). If you pass the strings to code that requires
122 | * valid UTF-8, you have to sanitize it in some way.
123 | * On Windows, filenames are always UTF-8, and libmpv converts
124 | * between UTF-8 and UTF-16 when using win32 API functions. See
125 | * the "Encoding of filenames" section for details.
126 | *
127 | * Example for reading:
128 | *
129 | * char *result = NULL;
130 | * if (mpv_get_property(ctx, "property", FORMAT_STRING, = C.MPV_FORMAT_STRING,
131 | * goto error;
132 | * printf("%s\n", result);
133 | * mpv_free(result);
134 | *
135 | * Or just use mpv_get_property_string().
136 | *
137 | * Example for writing:
138 | *
139 | * char *value = "the new value";
140 | * // yep, you pass the address to the variable
141 | * // (needed for symmetry with other types and mpv_get_property)
142 | * mpv_set_property(ctx, "property", FORMAT_STRING, = C.MPV_FORMAT_STRING,
143 | *
144 | * Or just use mpv_set_property_string().
145 | *
146 | */
147 | FORMAT_STRING Format = C.MPV_FORMAT_STRING
148 | /**
149 | * The basic type is char*. It returns the OSD property string, like
150 | * using ${property} in input.conf (see input.rst). In many cases, this
151 | * is the same as the raw string, but in other cases it's formatted for
152 | * display on OSD. It's intended to be human readable. Do not attempt to
153 | * parse these strings.
154 | *
155 | * Only valid when doing read access. The rest works like MPV_FORMAT_STRING.
156 | */
157 | FORMAT_OSD_STRING Format = C.MPV_FORMAT_OSD_STRING
158 | /**
159 | * The basic type is int. The only allowed values are 0 ("no")
160 | * and 1 ("yes").
161 | *
162 | * Example for reading:
163 | *
164 | * int result;
165 | * if (mpv_get_property(ctx, "property", FORMAT_FLAG, = C.MPV_FORMAT_FLAG,
166 | * goto error;
167 | * printf("%s\n", result ? "true" : "false");
168 | *
169 | * Example for writing:
170 | *
171 | * int flag = 1;
172 | * mpv_set_property(ctx, "property", FORMAT_STRING, = C.MPV_FORMAT_STRING,
173 | */
174 | FORMAT_FLAG Format = C.MPV_FORMAT_FLAG
175 | /**
176 | * The basic type is int64_t.
177 | */
178 | FORMAT_INT64 Format = C.MPV_FORMAT_INT64
179 | /**
180 | * The basic type is double.
181 | */
182 | FORMAT_DOUBLE Format = C.MPV_FORMAT_DOUBLE
183 | /**
184 | * The type is mpv_node.
185 | *
186 | * For reading, you usually would pass a pointer to a stack-allocated
187 | * mpv_node value to mpv, and when you're done you call
188 | * mpv_free_node_contents(&node).
189 | * You're expected not to write to the data - if you have to, copy it
190 | * first (which you have to do manually).
191 | *
192 | * For writing, you construct your own mpv_node, and pass a pointer to the
193 | * API. The API will never write to your data (and copy it if needed), so
194 | * you're free to use any form of allocation or memory management you like.
195 | *
196 | * Warning: when reading, always check the mpv_node.format member. For
197 | * example, properties might change their type in future versions
198 | * of mpv, or sometimes even during runtime.
199 | *
200 | * Example for reading:
201 | *
202 | * mpv_node result;
203 | * if (mpv_get_property(ctx, "property", FORMAT_NODE, = C.MPV_FORMAT_NODE,
204 | * goto error;
205 | * printf("format=%d\n", (int)result.format);
206 | * mpv_free_node_contents(&result).
207 | *
208 | * Example for writing:
209 | *
210 | * mpv_node value;
211 | * value.format = MPV_FORMAT_STRING;
212 | * value.u.string = "hello";
213 | * mpv_set_property(ctx, "property", FORMAT_NODE, = C.MPV_FORMAT_NODE,
214 | */
215 | FORMAT_NODE Format = C.MPV_FORMAT_NODE
216 | /**
217 | * Used with mpv_node only. Can usually not be used directly.
218 | */
219 | FORMAT_NODE_ARRAY Format = C.MPV_FORMAT_NODE_ARRAY
220 | /**
221 | * See MPV_FORMAT_NODE_ARRAY.
222 | */
223 | FORMAT_NODE_MAP Format = C.MPV_FORMAT_NODE_MAP
224 | /**
225 | * A raw, untyped byte array. Only used only with mpv_node, and only in
226 | * some very special situations. (Currently, only for the screenshot_raw
227 | * command.)
228 | */
229 | FORMAT_BYTE_ARRAY = C.MPV_FORMAT_BYTE_ARRAY
230 | )
231 |
232 | type EventId int
233 |
234 | //EventId mpv_event_id
235 | const (
236 | /**
237 | * Nothing happened. Happens on timeouts or sporadic wakeups.
238 | */
239 | EVENT_NONE EventId = C.MPV_EVENT_NONE
240 | /**
241 | * Happens when the player quits. The player enters a state where it tries
242 | * to disconnect all clients. Most requests to the player will fail, and
243 | * mpv_wait_event() will always return instantly (returning new shutdown
244 | * events if no other events are queued). The client should react to this
245 | * and quit with mpv_detach_destroy() as soon as possible.
246 | */
247 | EVENT_SHUTDOWN EventId = C.MPV_EVENT_SHUTDOWN
248 | /**
249 | * See mpv_request_log_messages().
250 | */
251 | EVENT_LOG_MESSAGE EventId = C.MPV_EVENT_LOG_MESSAGE
252 | /**
253 | * Reply to a mpv_get_property_async() request.
254 | * See also mpv_event and mpv_event_property.
255 | */
256 | EVENT_GET_PROPERTY_REPLY EventId = C.MPV_EVENT_GET_PROPERTY_REPLY
257 | /**
258 | * Reply to a mpv_set_property_async() request.
259 | * (Unlike EVENT_GET_PROPERTY, = C.MPV_EVENT_GET_PROPERTY,
260 | */
261 | EVENT_SET_PROPERTY_REPLY EventId = C.MPV_EVENT_SET_PROPERTY_REPLY
262 | /**
263 | * Reply to a mpv_command_async() request.
264 | */
265 | EVENT_COMMAND_REPLY EventId = C.MPV_EVENT_COMMAND_REPLY
266 | /**
267 | * Notification before playback start of a file (before the file is loaded).
268 | */
269 | EVENT_START_FILE EventId = C.MPV_EVENT_START_FILE
270 | /**
271 | * Notification after playback end (after the file was unloaded).
272 | * See also mpv_event and mpv_event_end_file.
273 | */
274 | EVENT_END_FILE EventId = C.MPV_EVENT_END_FILE
275 | /**
276 | * Notification when the file has been loaded (headers were read etc.), and
277 | * decoding starts.
278 | */
279 | EVENT_FILE_LOADED EventId = C.MPV_EVENT_FILE_LOADED
280 | /**
281 | * The list of video/audio/subtitle tracks was changed. (E.g. a new track
282 | * was found. This doesn't necessarily indicate a track switch; for this,
283 | * EVENT_TRACK_SWITCHED = C.MPV_EVENT_TRACK_SWITCHED
284 | *
285 | * @deprecated This is equivalent to using mpv_observe_property() on the
286 | * "track-list" property. The event is redundant, and might
287 | * be removed in the far future.
288 | */
289 | EVENT_TRACKS_CHANGED EventId = C.MPV_EVENT_TRACKS_CHANGED
290 | /**
291 | * A video/audio/subtitle track was switched on or off.
292 | *
293 | * @deprecated This is equivalent to using mpv_observe_property() on the
294 | * "vid", "aid", and "sid" properties. The event is redundant,
295 | * and might be removed in the far future.
296 | */
297 | EVENT_TRACK_SWITCHED EventId = C.MPV_EVENT_TRACK_SWITCHED
298 | /**
299 | * Idle mode was entered. In this mode, no file is played, and the playback
300 | * core waits for new commands. (The command line player normally quits
301 | * instead of entering idle mode, unless --idle was specified. If mpv
302 | * was started with mpv_create(), idle mode is enabled by default.)
303 | */
304 | EVENT_IDLE EventId = C.MPV_EVENT_IDLE
305 | /**
306 | * Playback was paused. This indicates the user pause state.
307 | *
308 | * The user pause state is the state the user requested (changed with the
309 | * "pause" property). There is an internal pause state too, which is entered
310 | * if e.g. the network is too slow (the "core-idle" property generally
311 | * indicates whether the core is playing or waiting).
312 | *
313 | * This event is sent whenever any pause states change, not only the user
314 | * state. You might get multiple events in a row while these states change
315 | * independently. But the event ID sent always indicates the user pause
316 | * state.
317 | *
318 | * If you don't want to deal with this, use mpv_observe_property() on the
319 | * "pause" property and ignore EVENT_PAUSE/UNPAUSE. = C.MPV_EVENT_PAUSE/UNPAUSE.
320 | * "core-idle" property tells you whether video is actually playing or not.
321 | *
322 | * @deprecated The event is redundant with mpv_observe_property() as
323 | * mentioned above, and might be removed in the far future.
324 | */
325 | EVENT_PAUSE EventId = C.MPV_EVENT_PAUSE
326 | /**
327 | * Playback was unpaused. See EVENT_PAUSE = C.MPV_EVENT_PAUSE
328 | *
329 | * @deprecated The event is redundant with mpv_observe_property() as
330 | * explained in the EVENT_PAUSE = C.MPV_EVENT_PAUSE
331 | * removed in the far future.
332 | */
333 | EVENT_UNPAUSE EventId = C.MPV_EVENT_UNPAUSE
334 | /**
335 | * Sent every time after a video frame is displayed. Note that currently,
336 | * this will be sent in lower frequency if there is no video, or playback
337 | * is paused - but that will be removed in the future, and it will be
338 | * restricted to video frames only.
339 | */
340 | EVENT_TICK EventId = C.MPV_EVENT_TICK
341 | /**
342 | * @deprecated This was used internally with the internal "script_dispatch"
343 | * command to dispatch keyboard and mouse input for the OSC.
344 | * It was never useful in general and has been completely
345 | * replaced with "script_binding".
346 | * This event never happens anymore, and is included in this
347 | * header only for compatibility.
348 | */
349 | EVENT_SCRIPT_INPUT_DISPATCH EventId = C.MPV_EVENT_SCRIPT_INPUT_DISPATCH
350 | /**
351 | * Triggered by the script_message input command. The command uses the
352 | * first argument of the command as client name (see mpv_client_name()) to
353 | * dispatch the message, and passes along all arguments starting from the
354 | * second argument as strings.
355 | * See also mpv_event and mpv_event_client_message.
356 | */
357 | EVENT_CLIENT_MESSAGE EventId = C.MPV_EVENT_CLIENT_MESSAGE
358 | /**
359 | * Happens after video changed in some way. This can happen on resolution
360 | * changes, pixel format changes, or video filter changes. The event is
361 | * sent after the video filters and the VO are reconfigured. Applications
362 | * embedding a mpv window should listen to this event in order to resize
363 | * the window if needed.
364 | * Note that this event can happen sporadically, and you should check
365 | * yourself whether the video parameters really changed before doing
366 | * something expensive.
367 | */
368 | EVENT_VIDEO_RECONFIG EventId = C.MPV_EVENT_VIDEO_RECONFIG
369 | /**
370 | * Similar to EVENT_VIDEO_RECONFIG. = C.MPV_EVENT_VIDEO_RECONFIG.
371 | * because there is no such thing as audio output embedding.
372 | */
373 | EVENT_AUDIO_RECONFIG EventId = C.MPV_EVENT_AUDIO_RECONFIG
374 | /**
375 | * Happens when metadata (like file tags) is possibly updated. (It's left
376 | * unspecified whether this happens on file start or only when it changes
377 | * within a file.)
378 | *
379 | * @deprecated This is equivalent to using mpv_observe_property() on the
380 | * "metadata" property. The event is redundant, and might
381 | * be removed in the far future.
382 | */
383 | EVENT_METADATA_UPDATE EventId = C.MPV_EVENT_METADATA_UPDATE
384 | /**
385 | * Happens when a seek was initiated. Playback stops. Usually it will
386 | * resume with EVENT_PLAYBACK_RESTART = C.MPV_EVENT_PLAYBACK_RESTART
387 | */
388 | EVENT_SEEK EventId = C.MPV_EVENT_SEEK
389 | /**
390 | * There was a discontinuity of some sort (like a seek), and playback
391 | * was reinitialized. Usually happens after seeking, or ordered chapter
392 | * segment switches. The main purpose is allowing the client to detect
393 | * when a seek request is finished.
394 | */
395 | EVENT_PLAYBACK_RESTART EventId = C.MPV_EVENT_PLAYBACK_RESTART
396 | /**
397 | * Event sent due to mpv_observe_property().
398 | * See also mpv_event and mpv_event_property.
399 | */
400 | EVENT_PROPERTY_CHANGE EventId = C.MPV_EVENT_PROPERTY_CHANGE
401 | /**
402 | * Happens when the current chapter changes.
403 | *
404 | * @deprecated This is equivalent to using mpv_observe_property() on the
405 | * "chapter" property. The event is redundant, and might
406 | * be removed in the far future.
407 | */
408 | EVENT_CHAPTER_CHANGE EventId = C.MPV_EVENT_CHAPTER_CHANGE
409 | /**
410 | * Happens if the internal per-mpv_handle ringbuffer overflows, and at
411 | * least 1 event had to be dropped. This can happen if the client doesn't
412 | * read the event queue quickly enough with mpv_wait_event(), or if the
413 | * client makes a very large number of asynchronous calls at once.
414 | *
415 | * Event delivery will continue normally once this event was returned
416 | * (this forces the client to empty the queue completely).
417 | */
418 | EVENT_QUEUE_OVERFLOW EventId = C.MPV_EVENT_QUEUE_OVERFLOW
419 | // Internal note: adjust INTERNAL_EVENT_BASE when adding new events.
420 | )
421 |
422 | func (eid EventId) String() string {
423 | switch eid {
424 | case EVENT_NONE:
425 | {
426 | return "EVENT_NONE"
427 | }
428 | case EVENT_SHUTDOWN:
429 | {
430 | return "EVENT_SHUTDOWN"
431 | }
432 | case EVENT_LOG_MESSAGE:
433 | {
434 | return "EVENT_LOG_MESSAGE"
435 | }
436 | case EVENT_GET_PROPERTY_REPLY:
437 | {
438 | return "EVENT_GET_PROPERTY_REPLY"
439 | }
440 | case EVENT_SET_PROPERTY_REPLY:
441 | {
442 | return "EVENT_SET_PROPERTY_REPLY"
443 | }
444 | case EVENT_COMMAND_REPLY:
445 | {
446 | return "EVENT_COMMAND_REPLY"
447 | }
448 | case EVENT_START_FILE:
449 | {
450 | return "EVENT_START_FILE"
451 | }
452 | case EVENT_END_FILE:
453 | {
454 | return "EVENT_END_FILE"
455 | }
456 | case EVENT_FILE_LOADED:
457 | {
458 | return "EVENT_FILE_LOADED"
459 | }
460 | case EVENT_TRACKS_CHANGED:
461 | {
462 | return "EVENT_TRACKS_CHANGED"
463 | }
464 | case EVENT_TRACK_SWITCHED:
465 | {
466 | return "EVENT_TRACK_SWITCHED"
467 | }
468 | case EVENT_IDLE:
469 | {
470 | return "EVENT_IDLE"
471 | }
472 | case EVENT_PAUSE:
473 | {
474 | return "EVENT_PAUSE"
475 | }
476 | case EVENT_UNPAUSE:
477 | {
478 | return "EVENT_UNPAUSE"
479 | }
480 | case EVENT_TICK:
481 | {
482 | return "EVENT_TICK"
483 | }
484 | case EVENT_SCRIPT_INPUT_DISPATCH:
485 | {
486 | return "EVENT_SCRIPT_INPUT_DISPATCH"
487 | }
488 | case EVENT_CLIENT_MESSAGE:
489 | {
490 | return "EVENT_CLIENT_MESSAGE"
491 | }
492 | case EVENT_VIDEO_RECONFIG:
493 | {
494 | return "EVENT_VIDEO_RECONFIG"
495 | }
496 | case EVENT_AUDIO_RECONFIG:
497 | {
498 | return "EVENT_AUDIO_RECONFIG"
499 | }
500 | case EVENT_METADATA_UPDATE:
501 | {
502 | return "EVENT_METADATA_UPDATE"
503 | }
504 | case EVENT_SEEK:
505 | {
506 | return "EVENT_SEEK"
507 | }
508 | case EVENT_PLAYBACK_RESTART:
509 | {
510 | return "EVENT_PLAYBACK_RESTART"
511 | }
512 | case EVENT_PROPERTY_CHANGE:
513 | {
514 | return "EVENT_PROPERTY_CHANGE"
515 | }
516 | case EVENT_CHAPTER_CHANGE:
517 | {
518 | return "EVENT_CHAPTER_CHANGE"
519 | }
520 | case EVENT_QUEUE_OVERFLOW:
521 | {
522 | return "EVENT_QUEUE_OVERFLOW"
523 | }
524 | }
525 | return "UNKNOWN_EVENT"
526 | }
527 |
528 | //Log level mpv_log_level
529 | const (
530 | LOG_LEVEL_NONE = C.MPV_LOG_LEVEL_NONE /// "no" - disable absolutely all messages
531 | LOG_LEVEL_FATAL = C.MPV_LOG_LEVEL_FATAL /// "fatal" - critical/aborting errors
532 | LOG_LEVEL_ERROR = C.MPV_LOG_LEVEL_ERROR /// "error" - simple errors
533 | LOG_LEVEL_WARN = C.MPV_LOG_LEVEL_WARN /// "warn" - possible problems
534 | LOG_LEVEL_INFO = C.MPV_LOG_LEVEL_INFO /// "info" - informational message
535 | LOG_LEVEL_V = C.MPV_LOG_LEVEL_V /// "v" - noisy informational message
536 | LOG_LEVEL_DEBUG = C.MPV_LOG_LEVEL_DEBUG /// "debug" - very noisy technical information
537 | LOG_LEVEL_TRACE = C.MPV_LOG_LEVEL_TRACE /// "trace" - extremely noisy
538 | )
539 |
540 | type EndFileReason int
541 |
542 | //EndFileReason mpv_end_file_reason
543 | const (
544 | /**
545 | * The end of file was reached. Sometimes this may also happen on
546 | * incomplete or corrupted files, or if the network connection was
547 | * interrupted when playing a remote file. It also happens if the
548 | * playback range was restricted with --end or --frames or similar.
549 | */
550 | END_FILE_REASON_EOF EndFileReason = C.MPV_END_FILE_REASON_EOF
551 | /**
552 | * Playback was stopped by an external action (e.g. playlist controls).
553 | */
554 | END_FILE_REASON_STOP EndFileReason = C.MPV_END_FILE_REASON_STOP
555 | /**
556 | * Playback was stopped by the quit command or player shutdown.
557 | */
558 | END_FILE_REASON_QUIT EndFileReason = C.MPV_END_FILE_REASON_QUIT
559 | /**
560 | * Some kind of error happened that lead to playback abort. Does not
561 | * necessarily happen on incomplete or broken files (in these cases, both
562 | * MPV_END_FILE_REASON_ERROR or MPV_END_FILE_REASON_EOF are possible).
563 | *
564 | * mpv_event_end_file.error will be set.
565 | */
566 | END_FILE_REASON_ERROR EndFileReason = C.MPV_END_FILE_REASON_ERROR
567 | /**
568 | * The file was a playlist or similar. When the playlist is read, its
569 | * entries will be appended to the playlist after the entry of the current
570 | * file, the entry of the current file is removed, and a MPV_EVENT_END_FILE
571 | * event is sent with reason set to MPV_END_FILE_REASON_REDIRECT. Then
572 | * playback continues with the playlist contents.
573 | * Since API version 1.18.
574 | */
575 | END_FILE_REASON_REDIRECT EndFileReason = C.MPV_END_FILE_REASON_REDIRECT
576 | )
577 |
578 | func (efr EndFileReason) String() string {
579 | switch efr {
580 | case END_FILE_REASON_EOF:
581 | return "END_FILE_REASON_EOF"
582 | case END_FILE_REASON_STOP:
583 | return "END_FILE_REASON_STOP"
584 | case END_FILE_REASON_QUIT:
585 | return "END_FILE_REASON_QUIT"
586 | case END_FILE_REASON_ERROR:
587 | return "END_FILE_REASON_ERROR"
588 | case END_FILE_REASON_REDIRECT:
589 | return "END_FILE_REASON_REDIRECT"
590 | default:
591 | return "END_FILE_REASON_UNKNOWN"
592 | }
593 | }
594 |
595 | type SubApi int
596 |
597 | //mpv_sub_api
598 | const (
599 | /**
600 | * For using mpv's OpenGL renderer on an external OpenGL context.
601 | * mpv_get_sub_api(MPV_SUB_API_OPENGL_CB) returns mpv_opengl_cb_context*.
602 | * This context can be used with mpv_opengl_cb_* functions.
603 | * Will return NULL if unavailable (if OpenGL support was not compiled in).
604 | * See opengl_cb.h for details.
605 | */
606 | SUB_API_OPENGL_CB SubApi = C.MPV_SUB_API_OPENGL_CB
607 | )
608 |
--------------------------------------------------------------------------------
/mpv/error.go:
--------------------------------------------------------------------------------
1 | package mpv
2 |
3 | //#include
4 | import "C"
5 |
6 | import (
7 | "fmt"
8 | )
9 |
10 | type Error int
11 |
12 | //const char *mpv_error_string(int error);
13 | func NewError(errcode C.int) error {
14 | if errcode == C.MPV_ERROR_SUCCESS {
15 | return nil
16 | }
17 | return Error(errcode)
18 | }
19 |
20 | func (m Error) Error() string {
21 | return fmt.Sprintln(int(m), C.GoString(C.mpv_error_string(C.int(m))))
22 | }
23 |
--------------------------------------------------------------------------------
/mpv/mpv.go:
--------------------------------------------------------------------------------
1 | package mpv
2 |
3 | /*
4 | #include
5 | #include
6 | #include
7 | #cgo LDFLAGS: -lmpv
8 |
9 | char** makeCharArray1(int size) {
10 | return calloc(sizeof(char*), size);
11 | }
12 | void setArrayString1(char** a, int i, char* s) {
13 | a[i] = s;
14 | }
15 |
16 | */
17 | import "C"
18 |
19 | import (
20 | "unsafe"
21 | )
22 |
23 | type Mpv struct {
24 | handle *C.mpv_handle
25 | wakeup_callbackVar interface{}
26 | wakeup_callbackFunc func(d interface{})
27 | }
28 |
29 | func Create() *Mpv {
30 | ctx := C.mpv_create()
31 | if ctx == nil {
32 | return nil
33 | }
34 | return &Mpv{ctx, nil, nil}
35 | }
36 |
37 | func (m *Mpv) ClientName() string {
38 | return C.GoString(C.mpv_client_name(m.handle))
39 | }
40 |
41 | func (m *Mpv) Initialize() error {
42 | return NewError(C.mpv_initialize(m.handle))
43 | }
44 |
45 | func (m *Mpv) DetachDestroy() {
46 | C.mpv_detach_destroy(m.handle)
47 | }
48 |
49 | func (m *Mpv) TerminateDestroy() {
50 | C.mpv_terminate_destroy(m.handle)
51 | }
52 |
53 | func (m *Mpv) CreateClient(name string) *Mpv {
54 | cname := C.CString(name)
55 | defer C.free(unsafe.Pointer(cname))
56 | cmpv := C.mpv_create_client(m.handle, cname)
57 | if cmpv != nil {
58 | return &Mpv{cmpv, nil, nil}
59 | }
60 | return nil
61 | }
62 |
63 | func (m *Mpv) LoadConfigFile(fileName string) error {
64 | cfn := C.CString(fileName)
65 | defer C.free(unsafe.Pointer(cfn))
66 | return NewError(C.mpv_load_config_file(m.handle, cfn))
67 | }
68 |
69 | func (m *Mpv) Suspend() {
70 | C.mpv_suspend(m.handle)
71 | }
72 |
73 | func (m *Mpv) Resume() {
74 | C.mpv_resume(m.handle)
75 | }
76 |
77 | func (m *Mpv) GetTimeUS() int64 {
78 | return int64(C.mpv_get_time_us(m.handle))
79 | }
80 |
81 | func (m *Mpv) SetOption(name string, format Format, data interface{}) error {
82 | cname := C.CString(name)
83 | defer C.free(unsafe.Pointer(cname))
84 | ptr := data2Ptr(format, data)
85 | return NewError(C.mpv_set_option(m.handle, cname, C.mpv_format(format), ptr))
86 | }
87 |
88 | func (m *Mpv) SetOptionString(name, data string) error {
89 | cname := C.CString(name)
90 | cdata := C.CString(data)
91 | defer C.free(unsafe.Pointer(cname))
92 | defer C.free(unsafe.Pointer(cdata))
93 | return NewError(C.mpv_set_option_string(m.handle, cname, cdata))
94 | }
95 |
96 | func (m *Mpv) Command(command []string) error {
97 | cArray := C.makeCharArray1(C.int(len(command) + 1))
98 | if cArray == nil {
99 | panic("got NULL from calloc")
100 | }
101 | defer C.free(unsafe.Pointer(cArray))
102 |
103 | for i, s := range command {
104 | cStr := C.CString(s)
105 | C.setArrayString1(cArray, C.int(i), cStr)
106 | defer C.free(unsafe.Pointer(cStr))
107 | }
108 |
109 | return NewError(C.mpv_command(m.handle, cArray))
110 | }
111 |
112 | func (m *Mpv) CommandNode(command []string) int {
113 | //int mpv_command_node(mpv_handle *ctx, mpv_node *args, mpv_node *result);
114 | //TODO
115 | panic("Not supported command")
116 | return -1
117 | }
118 |
119 | func (m *Mpv) CommandString(command string) error {
120 | ccmd := C.CString(command)
121 | defer C.free(unsafe.Pointer(ccmd))
122 | return NewError(C.mpv_command_string(m.handle, ccmd))
123 | }
124 |
125 | func (m *Mpv) CommandAsync(replyUserdata uint64, command []string) error {
126 | cArray := C.makeCharArray1(C.int(len(command) + 1))
127 | if cArray == nil {
128 | panic("got NULL from calloc")
129 | }
130 | defer C.free(unsafe.Pointer(cArray))
131 |
132 | for i, s := range command {
133 | cStr := C.CString(s)
134 | C.setArrayString1(cArray, C.int(i), cStr)
135 | defer C.free(unsafe.Pointer(cStr))
136 | }
137 |
138 | return NewError(C.mpv_command_async(m.handle, C.uint64_t(replyUserdata), cArray))
139 | }
140 |
141 | func (m *Mpv) CommandNodeAsync(command []string) int {
142 | //int mpv_command_node_async(mpv_handle *ctx, uint64_t reply_userdata, mpv_node *args);
143 | //TODO
144 | panic("Not supported command")
145 | return -1
146 | }
147 |
148 | func (m *Mpv) SetProperty(name string, format Format, data interface{}) error {
149 | cname := C.CString(name)
150 | defer C.free(unsafe.Pointer(cname))
151 | ptr := data2Ptr(format, data)
152 | return NewError(C.mpv_set_property(m.handle, cname, C.mpv_format(format), ptr))
153 | }
154 |
155 | func (m *Mpv) SetPropertyString(name, data string) error {
156 | cname := C.CString(name)
157 | cdata := C.CString(data)
158 | defer C.free(unsafe.Pointer(cname))
159 | defer C.free(unsafe.Pointer(cdata))
160 | return NewError(C.mpv_set_property_string(m.handle, cname, cdata))
161 | }
162 |
163 | func (m *Mpv) SetPropertyAsync(name string, replyUserdata uint64, format Format, data interface{}) error {
164 | cname := C.CString(name)
165 | defer C.free(unsafe.Pointer(cname))
166 | ptr := data2Ptr(format, data)
167 | return NewError(C.mpv_set_property_async(m.handle, C.uint64_t(replyUserdata), cname, C.mpv_format(format), ptr))
168 | }
169 |
170 | func (m *Mpv) GetProperty(name string, format Format) (interface{}, error) {
171 | cname := C.CString(name)
172 | defer C.free(unsafe.Pointer(cname))
173 |
174 | switch format {
175 | case FORMAT_STRING, FORMAT_OSD_STRING:
176 | {
177 | var cval *C.char
178 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval)))
179 | if err != nil {
180 | return nil, err
181 | }
182 | defer C.mpv_free(unsafe.Pointer(cval))
183 | return C.GoString(cval), nil
184 | }
185 | case FORMAT_INT64:
186 | {
187 | var cval C.int64_t
188 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval)))
189 | if err != nil {
190 | return nil, err
191 | }
192 | return int64(cval), nil
193 | }
194 | case FORMAT_DOUBLE:
195 | {
196 | var cval C.double
197 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval)))
198 | if err != nil {
199 | return nil, err
200 | }
201 | return float64(cval), nil
202 | }
203 | case FORMAT_FLAG:
204 | {
205 | var cval C.int
206 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval)))
207 | if err != nil {
208 | return nil, err
209 | }
210 | return cval == 1, nil
211 | }
212 | case FORMAT_NONE:
213 | {
214 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), nil))
215 | if err != nil {
216 | return nil, err
217 | }
218 | return nil, nil
219 | }
220 | case FORMAT_NODE:
221 | {
222 | var cval C.mpv_node
223 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval)))
224 | if err != nil {
225 | return nil, err
226 | }
227 | return GetNode(&cval)
228 | }
229 | case FORMAT_NODE_ARRAY:
230 | {
231 | var cval C.mpv_node_list
232 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval)))
233 | if err != nil {
234 | return nil, err
235 | }
236 | return GetNodeList(&cval)
237 | }
238 | case FORMAT_NODE_MAP:
239 | {
240 | var cval C.mpv_node_list
241 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval)))
242 | if err != nil {
243 | return nil, err
244 | }
245 | return GetNodeMap(cval)
246 | }
247 | default:
248 | panic("Not supported format")
249 | }
250 | }
251 |
252 | func (m *Mpv) GetPropertyString(name string) string {
253 | cname := C.CString(name)
254 | defer C.free(unsafe.Pointer(cname))
255 |
256 | cstr := C.mpv_get_property_string(m.handle, cname)
257 | if cstr != nil {
258 | str := C.GoString(cstr)
259 | C.mpv_free(unsafe.Pointer(cstr))
260 | return str
261 | }
262 |
263 | return ""
264 | }
265 |
266 | func (m *Mpv) GetPropertyOsdString(name string) string {
267 | cname := C.CString(name)
268 | defer C.free(unsafe.Pointer(cname))
269 | cstr := C.mpv_get_property_osd_string(m.handle, cname)
270 | if cstr != nil {
271 | str := C.GoString(cstr)
272 | C.mpv_free(unsafe.Pointer(cstr))
273 | return str
274 | }
275 |
276 | return ""
277 | }
278 |
279 | func (m *Mpv) GetPropertyAsync(name string, replyUserdata uint64, format Format) error {
280 | cname := C.CString(name)
281 | defer C.free(unsafe.Pointer(cname))
282 |
283 | return NewError(C.mpv_get_property_async(m.handle, C.uint64_t(replyUserdata), cname, C.mpv_format(format)))
284 | }
285 |
286 | func (m *Mpv) ObserveProperty(replyUserdata uint64, name string, format Format) error {
287 | cname := C.CString(name)
288 | defer C.free(unsafe.Pointer(cname))
289 | return NewError(C.mpv_observe_property(m.handle, C.uint64_t(replyUserdata), cname, C.mpv_format(format)))
290 | }
291 |
292 | func (m *Mpv) UnObserveProperty(registeredReplyUserdata uint64) error {
293 | return NewError(C.mpv_unobserve_property(m.handle, C.uint64_t(registeredReplyUserdata)))
294 | }
295 |
296 | func (m *Mpv) RequestEvent(event EventId, enable bool) error {
297 | var en C.int = 0
298 | if enable {
299 | en = 1
300 | }
301 | return NewError(C.mpv_request_event(m.handle, C.mpv_event_id(event), en))
302 | }
303 |
304 | func (m *Mpv) RequestLogMessages(minLevel string) error {
305 | clevel := C.CString(minLevel)
306 | defer C.free(unsafe.Pointer(clevel))
307 | return NewError(C.mpv_request_log_messages(m.handle, clevel))
308 | }
309 |
310 | func (m *Mpv) WaitEvent(timeout float32) *Event {
311 | var cevent *C.mpv_event
312 | cevent = C.mpv_wait_event(m.handle, C.double(timeout))
313 | if cevent == nil {
314 | return nil
315 | }
316 |
317 | e := &Event{}
318 |
319 | e.Event_Id = EventId(cevent.event_id)
320 | e.Reply_Userdata = uint64(cevent.reply_userdata)
321 | e.Error = NewError(cevent.error)
322 | if e.Event_Id == EVENT_END_FILE {
323 | var eef *C.mpv_event_end_file = (*C.struct_mpv_event_end_file)(cevent.data)
324 | efr := EventEndFile{}
325 | efr.Reason = EndFileReason(eef.reason)
326 | efr.ErrCode = Error(eef.error)
327 | e.Data = efr
328 | } else {
329 | e.Data = cevent.data
330 | }
331 | return e
332 | }
333 |
334 | func (m *Mpv) Wakeup() {
335 | C.mpv_wakeup(m.handle)
336 | }
337 |
338 | func (m *Mpv) SetWakeupCallback(callback func(d interface{}), d interface{}) {
339 | /*callbackFunc = callback
340 | callbackVar = d*/
341 | // C.mpv_set_wakeup_callback(m.handle,,unsafe.Pointer(d))
342 | //TODO void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d);
343 | panic("Not supported mpv_set_wakeup_callback")
344 | }
345 |
346 | func (m *Mpv) GetWakeupPipe() int {
347 | return int(C.mpv_get_wakeup_pipe(m.handle))
348 | }
349 |
350 | func (m *Mpv) WaitAsyncRequests() {
351 | C.mpv_wait_async_requests(m.handle)
352 | }
353 |
354 | func (m *Mpv) GetSubApi(api SubApi) unsafe.Pointer {
355 | return unsafe.Pointer(C.mpv_get_sub_api(m.handle, C.mpv_sub_api(api)))
356 | }
357 |
358 | func (m *Mpv) GetSubApiGL() *MpvGL {
359 | mgl := &MpvGL{}
360 | mgl.ctx = (*C.mpv_opengl_cb_context)(C.mpv_get_sub_api(m.handle, C.MPV_SUB_API_OPENGL_CB))
361 | if mgl.ctx == nil {
362 | return nil
363 | }
364 | return mgl
365 | }
366 |
367 | func data2Ptr(format Format, data interface{}) unsafe.Pointer {
368 | var ptr unsafe.Pointer = nil
369 | switch format {
370 | case FORMAT_STRING, FORMAT_OSD_STRING:
371 | {
372 | ptr = unsafe.Pointer(&[]byte(data.(string))[0])
373 | }
374 | case FORMAT_INT64:
375 | {
376 | i, ok := data.(int64)
377 | if !ok {
378 | i = int64(data.(int))
379 | }
380 | val := C.int64_t(i)
381 | ptr = unsafe.Pointer(&val)
382 | }
383 | case FORMAT_DOUBLE:
384 | {
385 | val := C.double(data.(float64))
386 | ptr = unsafe.Pointer(&val)
387 | }
388 | case FORMAT_FLAG:
389 | {
390 | val := C.int(0)
391 | if data.(bool) {
392 | val = 1
393 | }
394 | ptr = unsafe.Pointer(&val)
395 | }
396 | case FORMAT_NONE:
397 | {
398 | return nil
399 | }
400 |
401 | case FORMAT_NODE:
402 | {
403 | val := (data.(*Node))
404 | cnode := val.GetCNode()
405 | ptr = unsafe.Pointer(cnode)
406 | }
407 |
408 | case FORMAT_NODE_ARRAY, FORMAT_NODE_MAP:
409 | {
410 | return nil
411 | }
412 | }
413 | return ptr
414 | }
415 |
416 | type Event struct {
417 | Event_Id EventId
418 | Error error
419 | Reply_Userdata uint64
420 | Data interface{}
421 | }
422 |
423 | type EventEndFile struct {
424 | Reason EndFileReason
425 | ErrCode Error
426 | }
427 |
--------------------------------------------------------------------------------
/mpv/mpvgl.go:
--------------------------------------------------------------------------------
1 | package mpv
2 |
3 | /*
4 | #include
5 | extern void* getProcAddr(void*fn_ctx,char* text);
6 |
7 | */
8 | import "C"
9 |
10 | import (
11 | "unsafe"
12 | )
13 |
14 | type MpvGL struct {
15 | ctx *C.mpv_opengl_cb_context
16 | }
17 |
18 | type get_proc_addr func(string) unsafe.Pointer
19 |
20 | var callback_get_proc_address_fn get_proc_addr
21 |
22 | //export getProcAddr
23 | func getProcAddr(fn_ctx unsafe.Pointer, name *C.char) unsafe.Pointer {
24 | if callback_get_proc_address_fn != nil {
25 | return callback_get_proc_address_fn(C.GoString(name))
26 | }
27 | return nil
28 | }
29 |
30 | func (mgl *MpvGL) InitGL() error {
31 | callback_get_proc_address_fn = getProcAddress
32 | return NewError(C.mpv_opengl_cb_init_gl(mgl.ctx,
33 | nil,
34 | (*[0]byte)(C.getProcAddr),
35 | nil))
36 | }
37 |
38 | func (mgl *MpvGL) Draw(fbo, width, height int) int {
39 | return int(C.mpv_opengl_cb_draw(mgl.ctx, C.int(fbo), C.int(width), C.int(-height)))
40 | }
41 |
42 | //@deprecated
43 | func (mgl *MpvGL) Render(fbo int, vp []int) int {
44 | return int(C.mpv_opengl_cb_render(mgl.ctx, C.int(fbo), (*C.int)(unsafe.Pointer(&vp[0]))))
45 | }
46 |
47 | func (mgl *MpvGL) ReportFlip(time int64) error {
48 | return NewError(C.mpv_opengl_cb_report_flip(mgl.ctx, C.int64_t(time)))
49 | }
50 |
51 | func (mgl *MpvGL) UninitGL() error {
52 | return NewError(C.mpv_opengl_cb_uninit_gl(mgl.ctx))
53 | }
54 |
--------------------------------------------------------------------------------
/mpv/node.go:
--------------------------------------------------------------------------------
1 | package mpv
2 |
3 | /*
4 | #include
5 |
6 | struct mpv_node* GetNodeFromList(struct mpv_node* list,int i){
7 | return &list[i];
8 | }
9 |
10 | char* GetString(char** strings,int i){
11 | return strings[i];
12 | }
13 |
14 | */
15 | import "C"
16 | import (
17 | "bytes"
18 | "encoding/binary"
19 | "log"
20 | "unsafe"
21 | )
22 |
23 | type Node struct {
24 | value interface{}
25 | format Format
26 | }
27 |
28 | func NewNode(value interface{}, format Format) *Node {
29 | n := &Node{}
30 | n.value = value
31 | n.format = format
32 | return n
33 | }
34 |
35 | func (n *Node) GetVal() interface{} {
36 | return n.value
37 | }
38 |
39 | func (n *Node) GetCNode() *C.mpv_node {
40 | ptr := data2Ptr(n.format, n.value)
41 | if ptr == nil {
42 | return nil
43 | }
44 | writer := new(bytes.Buffer)
45 | err := binary.Write(writer, binary.LittleEndian, uint64(uintptr(ptr)))
46 | if err != nil {
47 | log.Println("Error write bin", err)
48 | return nil
49 | }
50 | buf := writer.Bytes()
51 | node := &C.mpv_node{}
52 | for i := 0; i < len(buf) && i < 8; i++ {
53 | node.u[i] = buf[i]
54 | }
55 | node.format = C.mpv_format(n.format)
56 | return node
57 | }
58 |
59 | func GetNode(node *C.mpv_node) (*Node, error) {
60 | n := &Node{}
61 | var err error
62 | n.value, err = GetValue(node)
63 | n.format = Format(node.format)
64 | return n, err
65 | }
66 |
67 | func FreeMpvNode(cnode *C.mpv_node) {
68 | C.mpv_free_node_contents(cnode)
69 | }
70 |
71 | func GetValue(node *C.mpv_node) (interface{}, error) {
72 | format := Format(node.format)
73 | buf := bytes.NewReader(C.GoBytes(unsafe.Pointer(&node.u[0]), 8))
74 | var ptr uint64
75 | err := binary.Read(buf, binary.LittleEndian, &ptr)
76 | if err != nil {
77 | log.Println("Error binary read", err)
78 | return nil, err
79 | }
80 | switch format {
81 | case FORMAT_STRING:
82 | {
83 | var ret *C.char
84 | ret = (*C.char)((unsafe.Pointer)(uintptr(ptr)))
85 | return C.GoString(ret), nil
86 | }
87 | case FORMAT_FLAG:
88 | {
89 | var ret bool
90 | ret = *(*C.int)((unsafe.Pointer)(uintptr(ptr))) != 0
91 | return ret, nil
92 | }
93 | case FORMAT_INT64:
94 | {
95 | var ret C.int64_t
96 | ret = *(*C.int64_t)((unsafe.Pointer)(uintptr(ptr)))
97 | return int64(ret), nil
98 | }
99 | case FORMAT_DOUBLE:
100 | {
101 | var ret C.double
102 | ret = *(*C.double)((unsafe.Pointer)(uintptr(ptr)))
103 | return float64(ret), nil
104 | }
105 | case FORMAT_NODE:
106 | {
107 | var ret C.mpv_node
108 | ret = *(*C.mpv_node)((unsafe.Pointer)(uintptr(ptr)))
109 | return GetNode(&ret)
110 | }
111 | case FORMAT_NODE_ARRAY:
112 | {
113 | var ret C.mpv_node_list
114 | ret = *(*C.mpv_node_list)((unsafe.Pointer)(uintptr(ptr)))
115 | return GetNodeList(&ret)
116 | }
117 | case FORMAT_NODE_MAP:
118 | {
119 | var ret C.mpv_node_list
120 | ret = *(*C.mpv_node_list)((unsafe.Pointer)(uintptr(ptr)))
121 | return GetNodeMap(ret)
122 | }
123 | case FORMAT_BYTE_ARRAY:
124 | {
125 | var ret C.mpv_byte_array
126 | ret = *(*C.mpv_byte_array)((unsafe.Pointer)(uintptr(ptr)))
127 | return C.GoBytes(ret.data, C.int(ret.size)), nil
128 | }
129 | default:
130 | {
131 | return nil, nil
132 | }
133 | }
134 | }
135 |
136 | func GetNodeList(clist *C.mpv_node_list) ([]*Node, error) {
137 | nodes := make([]*Node, clist.num)
138 | var err error
139 | var n C.int
140 | for n = 0; n < clist.num; n++ {
141 | nodes[n], err = GetNode(C.GetNodeFromList(clist.values, n))
142 | if err != nil {
143 | return nil, err
144 | }
145 | }
146 | return nodes, nil
147 | }
148 |
149 | func GetCNodeList(list []*Node) *C.mpv_node_list {
150 | /*if len(list) <= 0 {
151 | return nil
152 | }
153 | cnlist := &C.mpv_node_list{}
154 | cnlist.num = C.int(len(list))
155 | carr := unsafe.NewArray(C.mpv_node, len(list))
156 | for i, n := range list {
157 | carr[i] = *n.GetCNode()
158 | }*/
159 | return nil
160 | }
161 |
162 | func GetNodeMap(cmap C.mpv_node_list) (map[string]*Node, error) {
163 | nodes, err := GetNodeList(&cmap)
164 | if err != nil {
165 | return nil, err
166 | }
167 | var mapnode map[string]*Node
168 | for i, n := range nodes {
169 | mapnode[C.GoString(C.GetString(cmap.keys, C.int(i)))] = n
170 | }
171 | return mapnode, nil
172 | }
173 |
--------------------------------------------------------------------------------
/mpv/node_test.go:
--------------------------------------------------------------------------------
1 | package mpv
2 |
3 | import (
4 | "log"
5 | "testing"
6 | )
7 |
8 | func TestNode(t *testing.T) {
9 | {
10 | val := "123456789"
11 | format := FORMAT_STRING
12 | node := NewNode(val, format)
13 | cnode := node.GetCNode()
14 | node, err := GetNode(cnode)
15 | log.Println("CNode:", cnode, "Node val:", node.GetVal().(string), "Error:", err)
16 | if cnode == nil {
17 | log.Fatal("Fail node convert string")
18 | }
19 | }
20 | {
21 | val := int64(0x7FFFFFFFFFFFFFFF)
22 | format := FORMAT_INT64
23 | node := NewNode(val, format)
24 | cnode := node.GetCNode()
25 | node, err := GetNode(cnode)
26 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err)
27 | if cnode == nil {
28 | log.Fatal("Fail node convert int64")
29 | }
30 | }
31 | {
32 | val := bool(true)
33 | format := FORMAT_FLAG
34 | node := NewNode(val, format)
35 | cnode := node.GetCNode()
36 | node, err := GetNode(cnode)
37 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err)
38 | if cnode == nil {
39 | log.Fatal("Fail node convert int64")
40 | }
41 | }
42 |
43 | {
44 | val := float64(1.7976931348623157E+308)
45 | format := FORMAT_DOUBLE
46 | node := NewNode(val, format)
47 | cnode := node.GetCNode()
48 | node, err := GetNode(cnode)
49 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err)
50 | if cnode == nil {
51 | log.Fatal("Fail node convert int64")
52 | }
53 | }
54 |
55 | {
56 | val := NewNode(123, FORMAT_INT64)
57 | format := FORMAT_NODE
58 | node := NewNode(val, format)
59 | cnode := node.GetCNode()
60 | node, err := GetNode(cnode)
61 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err)
62 | if cnode == nil {
63 | log.Fatal("Fail node convert int64")
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/mpv/procaddr.go:
--------------------------------------------------------------------------------
1 | package mpv
2 |
3 | //From go-gl
4 |
5 | /*
6 | #cgo windows CFLAGS: -DTAG_WINDOWS
7 | #cgo windows LDFLAGS: -lopengl32
8 | #cgo darwin CFLAGS: -DTAG_DARWIN
9 | #cgo darwin LDFLAGS: -framework OpenGL
10 | #cgo linux CFLAGS: -DTAG_LINUX
11 | #cgo linux LDFLAGS: -lGL
12 | #cgo egl CFLAGS: -DTAG_EGL
13 | #cgo egl LDFLAGS: -lEGL
14 | // Check the EGL tag first as it takes priority over the platform's default
15 | // configuration of WGL/GLX/CGL.
16 | #if defined(TAG_EGL)
17 | #include
18 | #include
19 | void* glGetProcAddress(const char* name) {
20 | return eglGetProcAddress(name);
21 | }
22 | #elif defined(TAG_WINDOWS)
23 | #define WIN32_LEAN_AND_MEAN 1
24 | #include
25 | #include
26 | static HMODULE ogl32dll = NULL;
27 | void* glGetProcAddress(const char* name) {
28 | void* pf = wglGetProcAddress((LPCSTR) name);
29 | if (pf) {
30 | return pf;
31 | }
32 | if (ogl32dll == NULL) {
33 | ogl32dll = LoadLibraryA("opengl32.dll");
34 | }
35 | return GetProcAddress(ogl32dll, (LPCSTR) name);
36 | }
37 | #elif defined(TAG_DARWIN)
38 | #include
39 | #include
40 | void* glGetProcAddress(const char* name) {
41 | return dlsym(RTLD_DEFAULT, name);
42 | }
43 | #elif defined(TAG_LINUX)
44 | #include
45 | #include
46 | void* glGetProcAddress(const char* name) {
47 | return glXGetProcAddress(name);
48 | }
49 | #endif
50 | */
51 | import "C"
52 | import "unsafe"
53 |
54 | func getProcAddress(namea string) unsafe.Pointer {
55 | cname := C.CString(namea)
56 | defer C.free(unsafe.Pointer(cname))
57 | return C.glGetProcAddress(cname)
58 | }
59 |
--------------------------------------------------------------------------------